summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/resources
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/resources
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/resources')
-rw-r--r--testing/web-platform/tests/resources/.gitignore3
-rw-r--r--testing/web-platform/tests/resources/.gitmodules3
-rw-r--r--testing/web-platform/tests/resources/.htaccess2
-rw-r--r--testing/web-platform/tests/resources/LICENSE30
-rw-r--r--testing/web-platform/tests/resources/docs/api.md704
-rw-r--r--testing/web-platform/tests/resources/docs/idlharness.md128
-rw-r--r--testing/web-platform/tests/resources/examples/apisample-error-worker.js3
-rw-r--r--testing/web-platform/tests/resources/examples/apisample-worker.js34
-rw-r--r--testing/web-platform/tests/resources/examples/apisample.htm175
-rw-r--r--testing/web-platform/tests/resources/examples/apisample10.html119
-rw-r--r--testing/web-platform/tests/resources/examples/apisample11.html99
-rw-r--r--testing/web-platform/tests/resources/examples/apisample12.html67
-rw-r--r--testing/web-platform/tests/resources/examples/apisample13.html132
-rw-r--r--testing/web-platform/tests/resources/examples/apisample14.html29
-rw-r--r--testing/web-platform/tests/resources/examples/apisample15.html26
-rw-r--r--testing/web-platform/tests/resources/examples/apisample16.html62
-rw-r--r--testing/web-platform/tests/resources/examples/apisample17.html59
-rw-r--r--testing/web-platform/tests/resources/examples/apisample2.htm19
-rw-r--r--testing/web-platform/tests/resources/examples/apisample3.htm17
-rw-r--r--testing/web-platform/tests/resources/examples/apisample4.htm16
-rw-r--r--testing/web-platform/tests/resources/examples/apisample5.htm18
-rw-r--r--testing/web-platform/tests/resources/examples/apisample6.html10
-rw-r--r--testing/web-platform/tests/resources/examples/apisample7.html10
-rw-r--r--testing/web-platform/tests/resources/examples/apisample8.html8
-rw-r--r--testing/web-platform/tests/resources/examples/apisample9.html7
-rw-r--r--testing/web-platform/tests/resources/idlharness.js1853
-rw-r--r--testing/web-platform/tests/resources/readme.md23
-rw-r--r--testing/web-platform/tests/resources/testharness.css102
-rw-r--r--testing/web-platform/tests/resources/testharness.js2682
-rw-r--r--testing/web-platform/tests/resources/testharnessreport.js17
-rw-r--r--testing/web-platform/tests/resources/webidl2/.gitignore4
-rw-r--r--testing/web-platform/tests/resources/webidl2/.gitmodules3
-rw-r--r--testing/web-platform/tests/resources/webidl2/.travis.yml3
-rw-r--r--testing/web-platform/tests/resources/webidl2/LICENSE21
-rw-r--r--testing/web-platform/tests/resources/webidl2/README.md760
-rw-r--r--testing/web-platform/tests/resources/webidl2/coverage.html341
-rw-r--r--testing/web-platform/tests/resources/webidl2/index.js1
-rw-r--r--testing/web-platform/tests/resources/webidl2/lib/webidl2.js1012
-rw-r--r--testing/web-platform/tests/resources/webidl2/lib/writer.js236
-rw-r--r--testing/web-platform/tests/resources/webidl2/package.json21
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid.js42
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/dict-required-default.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/enum.widl1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/maplike-1type.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/module.widl25
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableany.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/raises.widl18
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/scopedname.widl2
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/setlike-2types.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/special-omittable.widl8
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.idl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/idl/typedef-nested.widl22
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/dict-required-default.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/enum.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/maplike-1type.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/module.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableany.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableobjects.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/raises.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/readonly-iterable.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/scopedname.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/setlike-2types.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/special-omittable.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/stringconstants.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/invalid/json/typedef-nested.json4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/mocha.opts1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax.js41
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/allowany.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/array.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/attributes.widl14
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/callback.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/caller.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/constants.widl18
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/constructor.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary.widl15
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation-dos.widl33
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation.widl34
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/enum.widl10
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl18
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception.widl8
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/generic.widl17
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/getter-setter.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl44
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/implements.widl14
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/indexed-properties.widl12
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/inherits-getter.widl16
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/interface-inherits.widl12
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterable.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterator.widl35
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/legacyiterable.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/map.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/maplike.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/namedconstructor.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullable.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullableobjects.widl13
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/overloading.widl20
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/partial-interface.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/primitives.widl19
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/prototyperoot.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/putforwards.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/reg-operations.widl17
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/replaceable.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/sequence.widl12
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/serializer.widl64
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/setlike.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/static.widl11
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier.widl8
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasnull.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasundefined.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-nested.widl22
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef.widl22
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/typesuffixes.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/idl/variadic-operations.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/allowany.json109
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/array.json34
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/attributes.json56
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/callback.json119
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/caller.json47
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/constants.json141
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/constructor.json103
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary-inherits.json83
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary.json135
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation-dos.json10
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation.json10
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/enum.json115
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/equivalent-decl.json312
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/exception-inheritance.json37
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/exception.json35
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json30
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/generic.json181
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/getter-setter.json114
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json217
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/implements.json107
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/indexed-properties.json272
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/inherits-getter.json71
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/interface-inherits.json80
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/iterable.json55
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/iterator.json301
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/legacyiterable.json24
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/map.json29
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/maplike.json67
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/namedconstructor.json42
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/nointerfaceobject.json52
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/nullable.json48
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/nullableobjects.json99
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/operation-optional-arg.json93
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/overloading.json312
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/overridebuiltins.json69
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/partial-interface.json53
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/primitives.json300
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/prototyperoot.json33
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/putforwards.json54
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/reg-operations.json168
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/replaceable.json54
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/sequence.json113
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/serializer.json591
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/setlike.json47
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/static.json151
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-attribute.json50
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-custom.json88
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier.json52
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasnull.json90
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasundefined.json90
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-nested.json226
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json226
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/typesuffixes.json55
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json87
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/json/variadic-operations.json100
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/syntax/opt/typedef-nested.json3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js51
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/web/run-tests.js48
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/.gitignore3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/LICENSE202
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/Makefile158
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/README.md40
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl28
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/doc/widlproc.html1124
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/examples/Makefile79
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/examples/README41
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/examples/bondi.widl227
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/examples/filesystem.widl1038
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl27
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/examples/widlhtml.css100
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.c1827
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.h25
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/entities.h271
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.c560
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.h141
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/main.c63
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.c119
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.h31
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.c331
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.h65
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/os.h31
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.c1414
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.h19
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.c319
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.h27
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl828
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/Makefile91
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl1
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl25
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl18
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl2
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl8
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl14
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl18
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl11
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl33
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl34
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl8
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl18
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl8
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl44
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl14
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl12
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl16
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl12
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl35
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl13
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl4
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl20
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl19
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl17
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl5
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl64
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl11
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl6
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl9
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl8
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl22
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl3
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl7
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml44
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml27
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml38
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml32
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml21
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml85
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml51
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml44
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml47
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml59
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml61
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml52
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml111
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml31
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml23
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml43
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml107
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml51
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml92
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml44
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml48
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml132
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml99
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml30
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml60
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml28
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml29
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml46
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml30
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml113
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml34
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml29
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml112
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml23
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml27
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml70
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml28
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml32
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml296
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml37
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml58
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml29
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml44
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml29
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml40
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml40
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml100
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml25
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml26
-rw-r--r--testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml40
326 files changed, 28840 insertions, 0 deletions
diff --git a/testing/web-platform/tests/resources/.gitignore b/testing/web-platform/tests/resources/.gitignore
new file mode 100644
index 000000000..04fdeda1c
--- /dev/null
+++ b/testing/web-platform/tests/resources/.gitignore
@@ -0,0 +1,3 @@
+ROBIN-TODO.txt
+scratch
+node_modules
diff --git a/testing/web-platform/tests/resources/.gitmodules b/testing/web-platform/tests/resources/.gitmodules
new file mode 100644
index 000000000..89035729d
--- /dev/null
+++ b/testing/web-platform/tests/resources/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "webidl2"]
+ path = webidl2
+ url = https://github.com/darobin/webidl2.js.git
diff --git a/testing/web-platform/tests/resources/.htaccess b/testing/web-platform/tests/resources/.htaccess
new file mode 100644
index 000000000..fd46101ca
--- /dev/null
+++ b/testing/web-platform/tests/resources/.htaccess
@@ -0,0 +1,2 @@
+# make tests that use utf-16 not inherit the encoding for testharness.js et. al.
+AddCharset utf-8 .css .js
diff --git a/testing/web-platform/tests/resources/LICENSE b/testing/web-platform/tests/resources/LICENSE
new file mode 100644
index 000000000..45896e6be
--- /dev/null
+++ b/testing/web-platform/tests/resources/LICENSE
@@ -0,0 +1,30 @@
+W3C 3-clause BSD License
+
+http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of works must retain the original copyright notice,
+ this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the original copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of the W3C nor the names of its contributors may be
+ used to endorse or promote products derived from this work without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/testing/web-platform/tests/resources/docs/api.md b/testing/web-platform/tests/resources/docs/api.md
new file mode 100644
index 000000000..980f4246c
--- /dev/null
+++ b/testing/web-platform/tests/resources/docs/api.md
@@ -0,0 +1,704 @@
+## Introduction ##
+
+testharness.js provides a framework for writing testcases. It is intended to
+provide a convenient API for making common assertions, and to work both
+for testing synchronous and asynchronous DOM features in a way that
+promotes clear, robust, tests.
+
+## Basic Usage ##
+
+The test harness script can be used from HTML or SVG documents and web worker
+scripts.
+
+From an HTML or SVG document, start by importing both `testharness.js` and
+`testharnessreport.js` scripts into the document:
+
+```html
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+```
+
+Refer to the [Web Workers](#web-workers) section for details and an example on
+testing within a web worker.
+
+Within each file one may define one or more tests. Each test is atomic in the
+sense that a single test has a single result (`PASS`/`FAIL`/`TIMEOUT`/`NOTRUN`).
+Within each test one may have a number of asserts. The test fails at the first
+failing assert, and the remainder of the test is (typically) not run.
+
+If the file containing the tests is a HTML file, a table containing the test
+results will be added to the document after all tests have run. By default this
+will be added to a `div` element with `id=log` if it exists, or a new `div`
+element appended to `document.body` if it does not.
+
+NOTE: By default tests must be created before the load event fires. For ways
+to create tests after the load event, see "Determining when all tests
+are complete", below.
+
+## Synchronous Tests ##
+
+To create a synchronous test use the `test()` function:
+
+```js
+test(test_function, name, properties)
+```
+
+`test_function` is a function that contains the code to test. For example a
+trivial test for the DOM
+[`hasFeature()`](https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature)
+method (which is defined to always return true) would be:
+
+```js
+test(function() {
+ assert_true(document.implementation.hasFeature());
+}, "hasFeature() with no arguments")
+```
+
+The function passed in is run in the `test()` call.
+
+`properties` is a javascript object for passing extra options to the
+test. Currently it is only used to provide test-specific
+metadata, as described in the [metadata](#metadata) section below.
+
+## Asynchronous Tests ##
+
+Testing asynchronous features is somewhat more complex since the result of
+a test may depend on one or more events or other callbacks. The API provided
+for testing these features is intended to be rather low-level but hopefully
+applicable to many situations.
+
+To create a test, one starts by getting a `Test` object using `async_test`:
+
+```js
+async_test(name, properties)
+```
+
+e.g.
+
+```js
+var t = async_test("DOMContentLoaded")
+```
+
+Assertions can be added to the test by calling the step method of the test
+object with a function containing the test assertions:
+
+```js
+document.addEventListener("DOMContentLoaded", function() {
+ t.step(function() {
+ assert_true(e.bubbles, "bubbles should be true");
+ });
+});
+```
+
+When all the steps are complete, the `done()` method must be called:
+
+```js
+t.done();
+```
+
+As a convenience, `async_test` can also takes a function as first argument.
+This function is called with the test object as both its `this` object and
+first argument. The above example can be rewritten as:
+
+```js
+async_test(function(t) {
+ document.addEventListener("DOMContentLoaded", function() {
+ t.step(function() {
+ assert_true(e.bubbles, "bubbles should be true");
+ });
+ t.done();
+ });
+}, "DOMContentLoaded");
+```
+
+which avoids cluttering the global scope with references to async
+tests instances.
+
+The properties argument is identical to that for `test()`.
+
+In many cases it is convenient to run a step in response to an event or a
+callback. A convenient method of doing this is through the `step_func` method
+which returns a function that, when called runs a test step. For example
+
+```js
+document.addEventListener("DOMContentLoaded", t.step_func(function() {
+ assert_true(e.bubbles, "bubbles should be true");
+ t.done();
+});
+```
+
+As a further convenience, the `step_func` that calls `done()` can instead
+use `step_func_done`, as follows:
+
+```js
+document.addEventListener("DOMContentLoaded", t.step_func_done(function() {
+ assert_true(e.bubbles, "bubbles should be true");
+});
+```
+
+For asynchronous callbacks that should never execute, `unreached_func` can
+be used. For example:
+
+```js
+document.documentElement.addEventListener("DOMContentLoaded",
+ t.unreached_func("DOMContentLoaded should not be fired on the document element"));
+```
+
+Keep in mind that other tests could start executing before an Asynchronous
+Test is finished.
+
+## Promise Tests ##
+
+`promise_test` can be used to test APIs that are based on Promises:
+
+```js
+promise_test(test_function, name, properties)
+```
+
+`test_function` is a function that receives a test as an argument and returns a
+promise. The test completes when the returned promise resolves. The test fails
+if the returned promise rejects.
+
+E.g.:
+
+```js
+function foo() {
+ return Promise.resolve("foo");
+}
+
+promise_test(function() {
+ return foo()
+ .then(function(result) {
+ assert_equals(result, "foo", "foo should return 'foo'");
+ });
+}, "Simple example");
+```
+
+In the example above, `foo()` returns a Promise that resolves with the string
+"foo". The `test_function` passed into `promise_test` invokes `foo` and attaches
+a resolve reaction that verifies the returned value.
+
+Note that in the promise chain constructed in `test_function` assertions don't
+need to wrapped in `step` or `step_func` calls.
+
+Unlike Asynchronous Tests, Promise Tests don't start running until after the
+previous Promise Test finishes.
+
+`promise_rejects` can be used to test Promises that need to reject:
+
+```js
+promise_rejects(test_object, code, promise, description)
+```
+
+The `code` argument is equivalent to the same argument to the `assert_throws`
+function.
+
+Here's an example where the `bar()` function returns a Promise that rejects
+with a TypeError:
+
+```js
+function bar() {
+ return Promise.reject(new TypeError());
+}
+
+promise_test(function(t) {
+ return promise_rejects(t, new TypeError(), bar());
+}, "Another example");
+```
+
+`EventWatcher` is a constructor function that allows DOM events to be handled
+using Promises, which can make it a lot easier to test a very specific series
+of events, including ensuring that unexpected events are not fired at any point.
+
+Here's an example of how to use `EventWatcher`:
+
+```js
+var t = async_test("Event order on animation start");
+
+var animation = watchedNode.getAnimations()[0];
+var eventWatcher = new EventWatcher(watchedNode, ['animationstart',
+ 'animationiteration',
+ 'animationend']);
+
+eventWatcher.wait_for(t, 'animationstart').then(t.step_func(function() {
+ assertExpectedStateAtStartOfAnimation();
+ animation.currentTime = END_TIME; // skip to end
+ // We expect two animationiteration events then an animationend event on
+ // skipping to the end of the animation.
+ return eventWatcher.wait_for(['animationiteration',
+ 'animationiteration',
+ 'animationend']);
+})).then(t.step_func(function() {
+ assertExpectedStateAtEndOfAnimation();
+ t.done();
+}));
+```
+
+`wait_for` either takes the name of a single event and returns a Promise that
+will resolve after that event is fired at the watched node, or else it takes an
+array of the names of a series of events and returns a Promise that will
+resolve after that specific series of events has been fired at the watched node.
+
+`EventWatcher` will assert if an event occurs while there is no `wait_for`()
+created Promise waiting to be fulfilled, or if the event is of a different type
+to the type currently expected. This ensures that only the events that are
+expected occur, in the correct order, and with the correct timing.
+
+## Single Page Tests ##
+
+Sometimes, particularly when dealing with asynchronous behaviour,
+having exactly one test per page is desirable, and the overhead of
+wrapping everything in functions for isolation becomes
+burdensome. For these cases `testharness.js` support "single page
+tests".
+
+In order for a test to be interpreted as a single page test, then
+it must simply not call `test()` or `async_test()` anywhere on the page, and
+must call the `done()` function to indicate that the test is complete. All
+the `assert_*` functions are avaliable as normal, but are called without
+the normal step function wrapper. For example:
+
+```html
+<!doctype html>
+<title>Basic document.body test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <script>
+ assert_equals(document.body, document.getElementsByTagName("body")[0])
+ done()
+ </script>
+```
+
+The test title for single page tests is always taken from `document.title`.
+
+## Making assertions ##
+
+Functions for making assertions start `assert_`. The full list of
+asserts avaliable is documented in the [asserts](#list-of-assertions) section
+below. The general signature is
+
+```js
+assert_something(actual, expected, description)
+```
+
+although not all assertions precisely match this pattern e.g. `assert_true`
+only takes `actual` and `description` as arguments.
+
+The description parameter is used to present more useful error messages when
+a test fails
+
+NOTE: All asserts must be located in a `test()` or a step of an
+`async_test()`, unless the test is a single page test. Asserts outside
+these places won't be detected correctly by the harness and may cause
+unexpected exceptions that will lead to an error in the harness.
+
+## Cleanup ##
+
+Occasionally tests may create state that will persist beyond the test itself.
+In order to ensure that tests are independent, such state should be cleaned
+up once the test has a result. This can be achieved by adding cleanup
+callbacks to the test. Such callbacks are registered using the `add_cleanup`
+function on the test object. All registered callbacks will be run as soon as
+the test result is known. For example
+
+```js
+ test(function() {
+ var element = document.createElement("div");
+ element.setAttribute("id", "null");
+ document.body.appendChild(element);
+ this.add_cleanup(function() { document.body.removeChild(element) });
+ assert_equals(document.getElementById(null), element);
+ }, "Calling document.getElementById with a null argument.");
+```
+
+## Timeouts in Tests ##
+
+In general the use of timeouts in tests is discouraged because this is
+an observed source of instability in real tests when run on CI
+infrastructure. In particular if a test should fail when something
+doesn't happen, it is good practice to simply let the test run to the
+full timeout rather than trying to guess an appropriate shorter
+timeout to use.
+
+In other cases it may be necessary to use a timeout (e.g., for a test
+that only passes if some event is *not* fired). In this case it is
+*not* permitted to use the standard `setTimeout` function. Instead one
+must use the `step_timeout` function:
+
+```js
+async_test(function(t) {
+ var gotEvent = false;
+ document.addEventListener("DOMContentLoaded", t.step_func(function() {
+ assert_false(gotEvent, "Unexpected DOMContentLoaded event");
+ gotEvent = true;
+ t.step_timeout(function() { t.done(); }, 2000);
+ });
+}, "Only one DOMContentLoaded");
+```
+
+The difference between `setTimeout` and `step_timeout` is that the
+latter takes account of the timeout multiplier when computing the
+delay; e.g., in the above case a timeout multiplier of 2 would cause a
+pause of 4000ms before calling the callback. This makes it less likely
+to produce unstable results in slow configurations.
+
+Note that timeouts generally need to be a few seconds long in order to
+produce stable results in all test environments.
+
+For single-page tests, `step_timeout` is also available as a global
+function.
+
+## Harness Timeout ##
+
+The overall harness admits two timeout values `"normal"` (the
+default) and `"long"`, used for tests which have an unusually long
+runtime. After the timeout is reached, the harness will stop
+waiting for further async tests to complete. By default the
+timeouts are set to 10s and 60s, respectively, but may be changed
+when the test is run on hardware with different performance
+characteristics to a common desktop computer. In order to opt-in
+to the longer test timeout, the test must specify a meta element:
+
+```html
+<meta name="timeout" content="long">
+```
+
+Occasionally tests may have a race between the harness timing out and
+a particular test failing; typically when the test waits for some event
+that never occurs. In this case it is possible to use `test.force_timeout()`
+in place of `assert_unreached()`, to immediately fail the test but with a
+status of `TIMEOUT`. This should only be used as a last resort when it is
+not possible to make the test reliable in some other way.
+
+## Setup ##
+
+Sometimes tests require non-trivial setup that may fail. For this purpose
+there is a `setup()` function, that may be called with one or two arguments.
+The two argument version is:
+
+```js
+setup(func, properties)
+```
+
+The one argument versions may omit either argument.
+func is a function to be run synchronously. `setup()` becomes a no-op once
+any tests have returned results. Properties are global properties of the test
+harness. Currently recognised properties are:
+
+`explicit_done` - Wait for an explicit call to done() before declaring all
+tests complete (see below; implicitly true for single page tests)
+
+`output_document` - The document to which results should be logged. By default
+this is the current document but could be an ancestor document in some cases
+e.g. a SVG test loaded in an HTML wrapper
+
+`explicit_timeout` - disable file timeout; only stop waiting for results
+when the `timeout()` function is called (typically for use when integrating
+with some existing test framework that has its own timeout mechanism).
+
+`allow_uncaught_exception` - don't treat an uncaught exception as an error;
+needed when e.g. testing the `window.onerror` handler.
+
+`timeout_multiplier` - Multiplier to apply to per-test timeouts.
+
+## Determining when all tests are complete ##
+
+By default the test harness will assume there are no more results to come
+when:
+
+ 1. There are no `Test` objects that have been created but not completed
+ 2. The load event on the document has fired
+
+This behaviour can be overridden by setting the `explicit_done` property to
+true in a call to `setup()`. If `explicit_done` is true, the test harness will
+not assume it is done until the global `done()` function is called. Once `done()`
+is called, the two conditions above apply like normal.
+
+Dedicated and shared workers don't have an event that corresponds to the `load`
+event in a document. Therefore these worker tests always behave as if the
+`explicit_done` property is set to true. Service workers depend on the
+[install](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-install-event)
+event which is fired following the completion of [running the
+worker](https://html.spec.whatwg.org/multipage/workers.html#run-a-worker).
+
+## Generating tests ##
+
+There are scenarios in which is is desirable to create a large number of
+(synchronous) tests that are internally similar but vary in the parameters
+used. To make this easier, the `generate_tests` function allows a single
+function to be called with each set of parameters in a list:
+
+```js
+generate_tests(test_function, parameter_lists, properties)
+```
+
+For example:
+
+```js
+generate_tests(assert_equals, [
+ ["Sum one and one", 1+1, 2],
+ ["Sum one and zero", 1+0, 1]
+ ])
+```
+
+Is equivalent to:
+
+```js
+test(function() {assert_equals(1+1, 2)}, "Sum one and one")
+test(function() {assert_equals(1+0, 1)}, "Sum one and zero")
+```
+
+Note that the first item in each parameter list corresponds to the name of
+the test.
+
+The properties argument is identical to that for `test()`. This may be a
+single object (used for all generated tests) or an array.
+
+## Callback API ##
+
+The framework provides callbacks corresponding to 4 events:
+
+ * `start` - triggered when the first Test is created
+ * `test_state` - triggered when a test state changes
+ * `result` - triggered when a test result is received
+ * `complete` - triggered when all results are received
+
+The page defining the tests may add callbacks for these events by calling
+the following methods:
+
+ `add_start_callback(callback)` - callback called with no arguments
+
+ `add_test_state_callback(callback)` - callback called with a test argument
+
+ `add_result_callback(callback)` - callback called with a test argument
+
+ `add_completion_callback(callback)` - callback called with an array of tests
+ and an status object
+
+tests have the following properties:
+
+ * `status` - A status code. This can be compared to the `PASS`, `FAIL`,
+ `TIMEOUT` and `NOTRUN` properties on the test object
+
+ * `message` - A message indicating the reason for failure. In the future this
+ will always be a string
+
+ The status object gives the overall status of the harness. It has the
+ following properties:
+
+ * `status` - Can be compared to the `OK`, `ERROR` and `TIMEOUT` properties
+
+ * `message` - An error message set when the status is `ERROR`
+
+## External API ##
+
+In order to collect the results of multiple pages containing tests, the test
+harness will, when loaded in a nested browsing context, attempt to call
+certain functions in each ancestor and opener browsing context:
+
+ * start - `start_callback`
+ * test\_state - `test_state_callback`
+ * result - `result_callback`
+ * complete - `completion_callback`
+
+These are given the same arguments as the corresponding internal callbacks
+described above.
+
+## External API through cross-document messaging ##
+
+Where supported, the test harness will also send messages using cross-document
+messaging to each ancestor and opener browsing context. Since it uses the
+wildcard keyword (\*), cross-origin communication is enabled and script on
+different origins can collect the results.
+
+This API follows similar conventions as those described above only slightly
+modified to accommodate message event API. Each message is sent by the harness
+is passed a single vanilla object, available as the `data` property of the event
+object. These objects are structures as follows:
+
+ * start - `{ type: "start" }`
+ * test\_state - `{ type: "test_state", test: Test }`
+ * result - `{ type: "result", test: Test }`
+ * complete - `{ type: "complete", tests: [Test, ...], status: TestsStatus }`
+
+## Web Workers ##
+
+The `testharness.js` script can be used from within [dedicated workers, shared
+workers](https://html.spec.whatwg.org/multipage/workers.html) and [service
+workers](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/).
+
+Testing from a worker script is different from testing from an HTML document in
+several ways:
+
+* Workers have no reporting capability since they are runing in the background.
+ Hence they rely on `testharness.js` running in a companion client HTML document
+ for reporting.
+
+* Shared and service workers do not have a unique client document since there
+ could be more than one document that communicates with these workers. So a
+ client document needs to explicitly connect to a worker and fetch test results
+ from it using `fetch_tests_from_worker`. This is true even for a dedicated
+ worker. Once connected, the individual tests running in the worker (or those
+ that have already run to completion) will be automatically reflected in the
+ client document.
+
+* The client document controls the timeout of the tests. All worker scripts act
+ as if they were started with the `explicit_timeout` option (see the [Harness
+ timeout](#harness-timeout) section).
+
+* Dedicated and shared workers don't have an equivalent of an `onload` event.
+ Thus the test harness has no way to know when all tests have completed (see
+ [Determining when all tests are
+ complete](#determining-when-all-tests-are-complete)). So these worker tests
+ behave as if they were started with the `explicit_done` option. Service
+ workers depend on the
+ [oninstall](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-install-event)
+ event and don't require an explicit `done` call.
+
+Here's an example that uses a dedicated worker.
+
+`worker.js`:
+
+```js
+importScripts("/resources/testharness.js");
+
+test(function(t) {
+ assert_true(true, "true is true");
+}, "Simple test");
+
+// done() is needed because the testharness is running as if explicit_done
+// was specified.
+done();
+```
+
+`test.html`:
+
+```html
+<!DOCTYPE html>
+<title>Simple test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+fetch_tests_from_worker(new Worker("worker.js"));
+
+</script>
+```
+
+The argument to the `fetch_tests_from_worker` function can be a
+[`Worker`](https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface),
+a [`SharedWorker`](https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworker-interface)
+or a [`ServiceWorker`](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-obj).
+Once called, the containing document fetches all the tests from the worker and
+behaves as if those tests were running in the containing document itself.
+
+## List of Assertions ##
+
+### `assert_true(actual, description)`
+asserts that `actual` is strictly true
+
+### `assert_false(actual, description)`
+asserts that `actual` is strictly false
+
+### `assert_equals(actual, expected, description)`
+asserts that `actual` is the same value as `expected`
+
+### `assert_not_equals(actual, expected, description)`
+asserts that `actual` is a different value to `expected`.
+This means that `expected` is a misnomer.
+
+### `assert_in_array(actual, expected, description)`
+asserts that `expected` is an Array, and `actual` is equal to one of the
+members i.e. `expected.indexOf(actual) != -1`
+
+### `assert_array_equals(actual, expected, description)`
+asserts that `actual` and `expected` have the same
+length and the value of each indexed property in `actual` is the strictly equal
+to the corresponding property value in `expected`
+
+### `assert_approx_equals(actual, expected, epsilon, description)`
+asserts that `actual` is a number within ±`epsilon` of `expected`
+
+### `assert_less_than(actual, expected, description)`
+asserts that `actual` is a number less than `expected`
+
+### `assert_greater_than(actual, expected, description)`
+asserts that `actual` is a number greater than `expected`
+
+### `assert_between_exclusive(actual, lower, upper, description`
+asserts that `actual` is a number between `lower` and `upper` but not
+equal to either of them
+
+### `assert_less_than_equal(actual, expected, description)`
+asserts that `actual` is a number less than or equal to `expected`
+
+### `assert_greater_than_equal(actual, expected, description)`
+asserts that `actual` is a number greater than or equal to `expected`
+
+### `assert_between_inclusive(actual, lower, upper, description`
+asserts that `actual` is a number between `lower` and `upper` or
+equal to either of them
+
+### `assert_regexp_match(actual, expected, description)`
+asserts that `actual` matches the regexp `expected`
+
+### `assert_class_string(object, class_name, description)`
+asserts that the class string of `object` as returned in
+`Object.prototype.toString` is equal to `class_name`.
+
+### `assert_own_property(object, property_name, description)`
+assert that object has own property `property_name`
+
+### `assert_inherits(object, property_name, description)`
+assert that object does not have an own property named
+`property_name` but that `property_name` is present in the prototype
+chain for object
+
+### `assert_idl_attribute(object, attribute_name, description)`
+assert that an object that is an instance of some interface has the
+attribute attribute_name following the conditions specified by WebIDL
+
+### `assert_readonly(object, property_name, description)`
+assert that property `property_name` on object is readonly
+
+### `assert_throws(code, func, description)`
+`code` - the expected exception. This can take several forms:
+
+ * string - the thrown exception must be a DOMException with the given
+ name, e.g., "TimeoutError" (for compatibility with existing
+ tests, a constant is also supported, e.g., "TIMEOUT_ERR")
+ * object - the thrown exception must have a property called "name" that
+ matches code.name
+ * null - allow any exception (in general, one of the options above
+ should be used)
+
+`func` - a function that should throw
+
+### `assert_unreached(description)`
+asserts if called. Used to ensure that some codepath is *not* taken e.g.
+an event does not fire.
+
+### `assert_any(assert_func, actual, expected_array, extra_arg_1, ... extra_arg_N)`
+asserts that one `assert_func(actual, expected_array_N, extra_arg1, ..., extra_arg_N)`
+ is true for some `expected_array_N` in `expected_array`. This only works for `assert_func`
+ with signature `assert_func(actual, expected, args_1, ..., args_N)`. Note that tests
+ with multiple allowed pass conditions are bad practice unless the spec specifically
+ allows multiple behaviours. Test authors should not use this method simply to hide
+ UA bugs.
+
+### `assert_exists(object, property_name, description)`
+**deprecated**
+asserts that object has an own property `property_name`
+
+### `assert_not_exists(object, property_name, description)`
+**deprecated**
+assert that object does not have own property `property_name`
+
+## Metadata ##
+
+It is possible to add optional metadata to tests; this can be done in
+one of two ways; either by adding `<meta>` elements to the head of the
+document containing the tests, or by adding the metadata to individual
+`[async_]test` calls, as properties.
diff --git a/testing/web-platform/tests/resources/docs/idlharness.md b/testing/web-platform/tests/resources/docs/idlharness.md
new file mode 100644
index 000000000..141077b3a
--- /dev/null
+++ b/testing/web-platform/tests/resources/docs/idlharness.md
@@ -0,0 +1,128 @@
+## Introduction ##
+
+`idlharness.js` automatically generates browser tests for WebIDL interfaces, using
+the testharness.js framework. To use, first include the following:
+
+```html
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+```
+
+Then you'll need some type of IDLs. Here's some script that can be run on a
+spec written in HTML, which will grab all the elements with `class="idl"`,
+concatenate them, and replace the body so you can copy-paste:
+
+```js
+var s = "";
+[].forEach.call(document.getElementsByClassName("idl"), function(idl) {
+ //https://www.w3.org/Bugs/Public/show_bug.cgi?id=14914
+ if (!idl.classList.contains("extract"))
+ {
+ s += idl.textContent + "\n\n";
+ }
+});
+document.body.innerHTML = '<pre></pre>';
+document.body.firstChild.textContent = s;
+```
+
+Once you have that, put it in your script somehow. The easiest way is to
+embed it literally in an HTML file with `<script type=text/plain>` or similar,
+so that you don't have to do any escaping. Another possibility is to put it
+in a separate .idl file that's fetched via XHR or similar. Sample usage:
+
+```js
+var idl_array = new IdlArray();
+idl_array.add_untested_idls("interface Node { readonly attribute DOMString nodeName; };");
+idl_array.add_idls("interface Document : Node { readonly attribute DOMString URL; };");
+idl_array.add_objects({Document: ["document"]});
+idl_array.test();
+```
+
+This tests that `window.Document` exists and meets all the requirements of
+WebIDL. It also tests that window.document (the result of evaluating the
+string "document") has URL and nodeName properties that behave as they
+should, and otherwise meets WebIDL's requirements for an object whose
+primary interface is Document. It does not test that window.Node exists,
+which is what you want if the Node interface is already tested in some other
+specification's suite and your specification only extends or refers to it.
+Of course, each IDL string can define many different things, and calls to
+add_objects() can register many different objects for different interfaces:
+this is a very simple example.
+
+## Public methods of IdlArray ##
+
+IdlArray objects can be obtained with `new IdlArray()`. Anything not
+documented in this section should be considered an implementation detail,
+and outside callers should not use it.
+
+### `add_idls(idl_string)`
+ Parses `idl_string` (throwing on parse error) and adds the results to the
+ IdlArray. All the definitions will be tested when you run test(). If
+ some of the definitions refer to other definitions, those must be present
+ too. For instance, if `idl_string` says that `Document` inherits from `Node`,
+ the `Node` interface must also have been provided in some call to `add_idls()`
+ or `add_untested_idls()`.
+
+### `add_untested_idls(idl_string)`
+ Like `add_idls()`, but the definitions will not be tested. If an untested
+ interface is added and then extended with a tested partial interface, the
+ members of the partial interface will still be tested. Also, all the
+ members will still be tested for objects added with `add_objects()`, because
+ you probably want to test that (for instance) window.document has all the
+ properties from `Node`, not just `Document`, even if the `Node` interface itself
+ is tested in a different test suite.
+
+### `add_objects(dict)`
+ `dict` should be an object whose keys are the names of interfaces or
+ exceptions, and whose values are arrays of strings. When an interface or
+ exception is tested, every string registered for it with `add_objects()`
+ will be evaluated, and tests will be run on the result to verify that it
+ correctly implements that interface or exception. This is the only way to
+ test anything about `[NoInterfaceObject]` interfaces, and there are many
+ tests that can't be run on any interface without an object to fiddle with.
+
+ The interface has to be the *primary* interface of all the objects
+ provided. For example, don't pass `{Node: ["document"]}`, but rather
+ `{Document: ["document"]}`. Assuming the `Document` interface was declared to
+ inherit from `Node`, this will automatically test that document implements
+ the `Node` interface too.
+
+ Warning: methods will be called on any provided objects, in a manner that
+ WebIDL requires be safe. For instance, if a method has mandatory
+ arguments, the test suite will try calling it with too few arguments to
+ see if it throws an exception. If an implementation incorrectly runs the
+ function instead of throwing, this might have side effects, possibly even
+ preventing the test suite from running correctly.
+
+### `prevent_multiple_testing(name)`
+ This is a niche method for use in case you're testing many objects that
+ implement the same interfaces, and don't want to retest the same
+ interfaces every single time. For instance, HTML defines many interfaces
+ that all inherit from `HTMLElement`, so the HTML test suite has something
+ like
+
+```js
+.add_objects({
+ HTMLHtmlElement: ['document.documentElement'],
+ HTMLHeadElement: ['document.head'],
+ HTMLBodyElement: ['document.body'],
+ ...
+})
+```
+
+ and so on for dozens of element types. This would mean that it would
+ retest that each and every one of those elements implements `HTMLElement`,
+ `Element`, and `Node`, which would be thousands of basically redundant tests.
+ The test suite therefore calls `prevent_multiple_testing("HTMLElement")`.
+ This means that once one object has been tested to implement `HTMLElement`
+ and its ancestors, no other object will be. Thus in the example code
+ above, the harness would test that `document.documentElement` correctly
+ implements `HTMLHtmlElement`, `HTMLElement`, `Element`, and `Node`; but
+ `document.head` would only be tested for `HTMLHeadElement`, and so on for
+ further objects.
+
+### `test()`
+ Run all tests. This should be called after you've called all other
+ methods to add IDLs and objects.
diff --git a/testing/web-platform/tests/resources/examples/apisample-error-worker.js b/testing/web-platform/tests/resources/examples/apisample-error-worker.js
new file mode 100644
index 000000000..9bfe0a6f3
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample-error-worker.js
@@ -0,0 +1,3 @@
+importScripts("../testharness.js");
+
+throw new Error("This failure is expected.");
diff --git a/testing/web-platform/tests/resources/examples/apisample-worker.js b/testing/web-platform/tests/resources/examples/apisample-worker.js
new file mode 100644
index 000000000..b1d086314
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample-worker.js
@@ -0,0 +1,34 @@
+importScripts("../testharness.js");
+
+test(
+ function(test) {
+ assert_true(true, "True is true");
+ },
+ "Worker test that completes successfully");
+
+test(
+ function(test) {
+ assert_true(false, "Failing test");
+ },
+ "Worker test that fails ('FAIL')");
+
+async_test(
+ function(test) {
+ assert_true(true, "True is true");
+ },
+ "Worker test that times out ('TIMEOUT')");
+
+async_test("Worker test that doesn't run ('NOT RUN')");
+
+async_test(
+ function(test) {
+ self.setTimeout(
+ function() {
+ test.done();
+ },
+ 0);
+ },
+ "Worker async_test that completes successfully");
+
+// An explicit done() is required for dedicated and shared web workers.
+done();
diff --git a/testing/web-platform/tests/resources/examples/apisample.htm b/testing/web-platform/tests/resources/examples/apisample.htm
new file mode 100644
index 000000000..504a343ac
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample.htm
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample HTML5 API Tests</title>
+<meta name="timeout" content="6000">
+</head>
+<body onload="load_test_attr.done()">
+<h1>Sample HTML5 API Tests</h1>
+<div id="log"></div>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+ setup_run = false;
+ setup(function() {
+ setup_run = true;
+ });
+ test(function() {assert_true(setup_run)}, "Setup function ran");
+
+ // Two examples for testing events from handler and attributes
+ var load_test_event = async_test("window onload event fires when set from the handler");
+
+ function windowLoad()
+ {
+ load_test_event.done();
+ }
+ on_event(window, "load", windowLoad);
+
+ // see the body onload below
+ var load_test_attr = async_test("body element fires the onload event set from the attribute");
+</script>
+<script>
+ function bodyElement()
+ {
+ assert_equals(document.body, document.getElementsByTagName("body")[0]);
+ }
+ test(bodyElement, "document.body should be the first body element in the document");
+
+ test(function() {
+ assert_equals(1,1);
+ assert_equals(NaN, NaN, "NaN case");
+ assert_equals(0, 0, "Zero case");
+ }, "assert_equals tests")
+
+ test(function() {
+ assert_equals(-0, 0, "Zero case");
+ }, "assert_equals tests expected to fail")
+
+ test(function() {
+ assert_not_equals({}, {}, "object case");
+ assert_not_equals(-0, 0, "Zero case");
+ }, "assert_not_equals tests")
+
+ function testAssertPass()
+ {
+ assert_true(true);
+ }
+ test(testAssertPass, "assert_true expected to pass");
+
+ function testAssertFalse()
+ {
+ assert_true(false, "false should not be true");
+ }
+ test(testAssertFalse, "assert_true expected to fail");
+
+ function basicAssertArrayEquals()
+ {
+ assert_array_equals([1, NaN], [1, NaN], "[1, NaN] is equal to [1, NaN]");
+ }
+ test(basicAssertArrayEquals, "basic assert_array_equals test");
+
+ function basicAssertObjectEquals()
+ {
+ assert_object_equals([1, 2, [1, 2]], { 0: 1, 1: 2, 2: { 0: 1, 1: 2} }, "array is equal to object")
+ }
+ test(basicAssertObjectEquals, "basic assert_object_equals test");
+
+ function basicAssertApproxEquals()
+ {
+ assert_approx_equals(10, 11, 1, "10 is approximately (+/- 1) 11")
+ }
+ test(basicAssertApproxEquals, "basic assert_approx_equals test");
+
+ function basicAssertLessThan()
+ {
+ assert_less_than(10, 11, "10 is less than 11")
+ }
+ test(basicAssertApproxEquals, "basic assert_less_than test");
+
+ function basicAssertGreaterThan()
+ {
+ assert_greater_than(10, 11, "10 is not greater than 11");
+ }
+ test(basicAssertGreaterThan, "assert_greater_than expected to fail");
+
+ function basicAssertGreaterThanEqual()
+ {
+ assert_greater_than_equal(10, 10, "10 is greater than or equal to 10")
+ }
+ test(basicAssertGreaterThanEqual, "basic assert_greater_than_equal test");
+
+ function basicAssertLessThanEqual()
+ {
+ assert_greater_than_equal('10', 10, "'10' is not a number")
+ }
+ test(basicAssertLessThanEqual, "assert_less_than_equal expected to fail");
+
+ function testAssertInherits() {
+ var A = function(){this.a = "a"}
+ A.prototype = {b:"b"}
+ var a = new A();
+ assert_exists(a, "a");
+ assert_not_exists(a, "b");
+ assert_inherits(a, "b");
+ }
+ test(testAssertInherits, "test for assert[_not]_exists and insert_inherits")
+
+ test(function()
+ {
+ var a = document.createElement("a")
+ var b = document.createElement("b")
+ assert_throws("NOT_FOUND_ERR", function(){a.removeChild(b)});
+ }, "Test throw DOM exception")
+
+ test(function()
+ {
+ var a = document.createTextNode("a")
+ var b = document.createElement("b")
+ assert_throws("NOT_FOUND_ERR", function(){a.appendChild(b)});
+ }, "Test throw DOM exception expected to fail")
+
+ test(function()
+ {
+ var e = {code:0, name:"TEST_ERR", TEST_ERR:0}
+ assert_throws("TEST_ERR", function() {throw e});
+ }, "Test assert_throws with non-DOM-exception expected to Fail");
+
+ var t = async_test("Test step_func")
+ setTimeout(
+ t.step_func(
+ function () {
+ assert_true(true); t.done();
+ }), 0);
+
+ async_test(function(t) {
+ setTimeout(t.step_func(function (){assert_true(true); t.done();}), 0);
+ }, "Test async test with callback");
+
+ async_test(function() {
+ setTimeout(this.step_func(function (){assert_true(true); this.done();}), 0);
+ }, "Test async test with callback and `this` obj.");
+
+ async_test("test should timeout (fail) with the default of 2 seconds").step(function(){});
+
+ async_test("test should timeout (fail) with a custom set timeout value of 1 second",
+ {timeout:1000}).step(function(){});
+
+ async_test("async test that is never started, should have status Not Run", {timeout:1000});
+
+
+ test(function(t) {
+ window.global = 1;
+ t.add_cleanup(function() {delete window.global});
+ assert_equals(window.global, 1);
+ },
+ "Test that defines a global and cleans it up");
+
+ test(function() {assert_equals(window.global, undefined)},
+ "Test that cleanup handlers from previous test ran");
+
+</script>
+</body>
+</html>
+
+
+
diff --git a/testing/web-platform/tests/resources/examples/apisample10.html b/testing/web-platform/tests/resources/examples/apisample10.html
new file mode 100644
index 000000000..69810fe16
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample10.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Async Tests and Promises</title>
+</head>
+<body>
+<h1>Async Tests and Promises</h1>
+<p>This test assumes ECMAScript 6 Promise support. Some failures are expected.</p>
+<div id="log"></div>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+
+test(function() {
+ var p = new Promise(function(resolve, reject) {});
+ assert_true('then' in p);
+ assert_equals(typeof Promise.resolve, 'function');
+ assert_equals(typeof Promise.reject, 'function');
+}, "Promises are supported in your browser");
+
+(function() {
+ var t = async_test("Promise resolution");
+ t.step(function() {
+ Promise.resolve('x').then(
+ t.step_func(function(value) {
+ assert_equals(value, 'x');
+ t.done();
+ }),
+ t.unreached_func('Promise should not reject')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Promise rejection");
+ t.step(function() {
+ Promise.reject(Error('fail')).then(
+ t.unreached_func('Promise should reject'),
+ t.step_func(function(reason) {
+ assert_true(reason instanceof Error);
+ assert_equals(reason.message, 'fail');
+ t.done();
+ })
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Promises resolution chaining");
+ t.step(function() {
+ var resolutions = [];
+ Promise.resolve('a').then(
+ t.step_func(function(value) {
+ resolutions.push(value);
+ return 'b';
+ })
+ ).then(
+ t.step_func(function(value) {
+ resolutions.push(value);
+ return 'c';
+ })
+ ).then(
+ t.step_func(function(value) {
+ resolutions.push(value);
+
+ assert_array_equals(resolutions, ['a', 'b', 'c']);
+ t.done();
+ })
+ ).catch(
+ t.unreached_func('promise should not have rejected')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Use of step_func with Promises");
+ t.step(function() {
+ var resolutions = [];
+ Promise.resolve('x').then(
+ t.step_func_done(),
+ t.unreached_func('Promise should not have rejected')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Promises and test assertion failures (should fail)");
+ t.step(function() {
+ var resolutions = [];
+ Promise.resolve('x').then(
+ t.step_func(function(value) {
+ assert_true(false, 'This failure is expected');
+ })
+ ).then(
+ t.unreached_func('Promise should not have resolved')
+ ).catch(
+ t.unreached_func('Promise should not have rejected')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Use of unreached_func with Promises (should fail)");
+ t.step(function() {
+ var resolutions = [];
+ var r;
+ var p = new Promise(function(resolve, reject) {
+ // Reject instead of resolve, to demonstrate failure.
+ reject(123);
+ });
+ p.then(
+ function(value) {
+ assert_equals(value, 123, 'This should not actually happen');
+ },
+ t.unreached_func('This failure is expected')
+ );
+ });
+}());
+</script>
diff --git a/testing/web-platform/tests/resources/examples/apisample11.html b/testing/web-platform/tests/resources/examples/apisample11.html
new file mode 100644
index 000000000..32e8984c3
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample11.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with iframe that notifies containing document via callbacks</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+</head>
+<body onload="start_test_in_iframe()">
+<h1>Callbacks From Tests Running In An IFRAME</h1>
+<p>A test is run inside an <tt>iframe</tt> with a same origin document. The
+containing document should receive callbacks as the tests progress inside the
+<tt>iframe</tt>. A single passing test is expected in the summary below.
+<div id="log"></div>
+
+<script>
+var callbacks = [];
+var START = 1
+var TEST_STATE = 2
+var RESULT = 3
+var COMPLETION = 4
+var test_complete = false;
+
+setup({explicit_done: true});
+
+// The following callbacks are called for tests in this document as well as the
+// tests in the IFRAME. Currently, callbacks invoked from this document and any
+// child document are indistinguishable from each other.
+
+function start_callback(properties) {
+ callbacks.push(START);
+}
+
+function test_state_callback(test) {
+ callbacks.push(TEST_STATE);
+}
+
+function result_callback(test) {
+ callbacks.push(RESULT);
+}
+
+function completion_callback(tests, status) {
+ if (test_complete) {
+ return;
+ }
+ test_complete = true;
+ callbacks.push(COMPLETION);
+ verify_received_callbacks();
+ done();
+}
+
+function verify_received_callbacks() {
+ var copy_of_callbacks = callbacks.slice(0);
+
+ // Note that you can't run test assertions directly in a callback even if
+ // this is a file test. When the callback is invoked from a same-origin child
+ // page, the callstack reaches into the calling child document. Any
+ // exception thrown in a callback will be handled by the child rather than
+ // this document.
+ test(
+ function() {
+ // callbacks list should look like:
+ // START 1*(TEST_STATE) RESULT COMPLETION
+ assert_equals(copy_of_callbacks.shift(), START,
+ "The first received callback should be 'start_callback'.");
+ assert_equals(copy_of_callbacks.shift(), TEST_STATE,
+ "'test_state_callback' should be received before any " +
+ "result or completion callbacks.");
+ while(copy_of_callbacks.length > 0) {
+ var callback = copy_of_callbacks.shift();
+ if (callback != TEST_STATE) {
+ copy_of_callbacks.unshift(callback);
+ break;
+ }
+ }
+ assert_equals(copy_of_callbacks.shift(), RESULT,
+ "'test_state_callback' should be followed by 'result_callback'.");
+ assert_equals(copy_of_callbacks.shift(), COMPLETION,
+ "Final 'result_callback' should be followed by 'completion_callback'.");
+ assert_equals(copy_of_callbacks.length, 0,
+ "'completion_callback' should be the last callback.");
+ });
+}
+
+function start_test_in_iframe() {
+ // This document is going to clear any received callbacks and maintain
+ // radio silence until the test in the iframe runs to completion. The
+ // completion_callback() will then complete the testing on this document.
+ callbacks.length = 0;
+ var iframe = document.createElement("iframe");
+ // apisample6.html has a single test.
+ iframe.src = "apisample6.html";
+ iframe.style.setProperty("display", "none");
+ document.getElementById("target").appendChild(iframe);
+}
+</script>
+
+<div id="target">
+</div>
+</body>
diff --git a/testing/web-platform/tests/resources/examples/apisample12.html b/testing/web-platform/tests/resources/examples/apisample12.html
new file mode 100644
index 000000000..785d57b2b
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample12.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with iframe that notifies containing document via cross document messaging</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+</head>
+<body>
+<h1>Notifications From Tests Running In An IFRAME</h1>
+<p>A test is run inside an <tt>iframe</tt> with a same origin document. The
+containing document should receive messages via <tt>postMessage</tt>/
+<tt>onmessage</tt> as the tests progress inside the <tt>iframe</tt>. A single
+passing test is expected in the summary below.
+</p>
+<div id="log"></div>
+
+<script>
+var t = async_test("Containing document receives messages");
+var start_received = false;
+var result_received = false;
+var completion_received = false;
+
+// These are the messages that are expected to be seen while running the tests
+// in the IFRAME.
+var expected_messages = [
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "start");
+ assert_own_property(message.data, "properties");
+ }),
+
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "test_state");
+ assert_equals(message.data.test.status, message.data.test.NOTRUN);
+ }),
+
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "result");
+ assert_equals(message.data.test.status, message.data.test.PASS);
+ }),
+
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "complete");
+ assert_equals(message.data.tests.length, 1);
+ assert_equals(message.data.tests[0].status,
+ message.data.tests[0].PASS);
+ assert_equals(message.data.status.status, message.data.status.OK);
+ t.done();
+ }),
+
+ t.unreached_func("Too many messages received")
+];
+
+on_event(window,
+ "message",
+ function(message) {
+ var handler = expected_messages.shift();
+ handler(message);
+ });
+</script>
+<iframe src="apisample6.html" style="display:none">
+ <!-- apisample6 implements a file_is_test test. -->
+</iframe>
+</body>
diff --git a/testing/web-platform/tests/resources/examples/apisample13.html b/testing/web-platform/tests/resources/examples/apisample13.html
new file mode 100644
index 000000000..f6cf0eec8
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample13.html
@@ -0,0 +1,132 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Promise Tests</title>
+</head>
+<body>
+<h1>Promise Tests</h1>
+<p>This test demonstrates the use of <tt>promise_test</tt>. Assumes ECMAScript 6
+Promise support. Some failures are expected.</p>
+<div id="log"></div>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+test(
+ function() {
+ var p = new Promise(function(resolve, reject){});
+ assert_true("then" in p);
+ assert_equals(typeof Promise.resolve, "function");
+ assert_equals(typeof Promise.reject, "function");
+ },
+ "Promises are supported in your browser");
+
+promise_test(
+ function() {
+ return Promise.resolve("x")
+ .then(
+ function(value) {
+ assert_equals(value,
+ "x",
+ "Fulfilled promise should pass result to " +
+ "fulfill reaction.");
+ });
+ },
+ "Promise fulfillment with result");
+
+promise_test(
+ function(t) {
+ return Promise.reject(new Error("fail"))
+ .then(t.unreached_func("Promise should reject"),
+ function(reason) {
+ assert_true(
+ reason instanceof Error,
+ "Rejected promise should pass reason to fulfill reaction.");
+ assert_equals(
+ reason.message,
+ "fail",
+ "Rejected promise should pass reason to reject reaction.");
+ });
+ },
+ "Promise rejection with result");
+
+promise_test(
+ function() {
+ var resolutions = [];
+ return Promise.resolve("a")
+ .then(
+ function(value) {
+ resolutions.push(value);
+ return "b";
+ })
+ .then(
+ function(value) {
+ resolutions.push(value);
+ return "c";
+ })
+ .then(
+ function(value) {
+ resolutions.push(value);
+ assert_array_equals(resolutions, ["a", "b", "c"]);
+ });
+ },
+ "Chain of promise resolutions");
+
+promise_test(
+ function(t) {
+ var resolutions = [];
+ return Promise.resolve("x")
+ .then(
+ function(value) {
+ assert_true(false, "Expected failure.");
+ })
+ .then(t.unreached_func("UNEXPECTED FAILURE: Promise should not have resolved."));
+ },
+ "Assertion failure in a fulfill reaction (should FAIL with an expected failure)");
+
+promise_test(
+ function(t) {
+ return new Promise(
+ function(resolve, reject) {
+ reject(123);
+ })
+ .then(t.unreached_func("UNEXPECTED FAILURE: Fulfill reaction reached after rejection."),
+ t.unreached_func("Expected failure."));
+ },
+ "unreached_func as reactor (should FAIL with an expected failure)");
+
+promise_test(
+ function() {
+ return true;
+ },
+ "promise_test with function that doesn't return a Promise");
+
+promise_test(function(){},
+ "promise_test with function that doesn't return anything");
+
+promise_test(
+ function() {
+ return Promise.reject("Expected rejection");
+ },
+ "promise_test with unhandled rejection (should FAIL)");
+
+promise_test(
+ function() {
+ return Promise.resolve(10)
+ .then(
+ function(value) {
+ throw Error("Expected exception.");
+ });
+ },
+ "promise_test with unhandled exception in fulfill reaction (should FAIL)");
+
+promise_test(
+ function(t) {
+ return Promise.reject(10)
+ .then(
+ t.unreached_func("UNEXPECTED FAILURE: Fulfill reaction reached after rejection."),
+ function(value) {
+ throw Error("Expected exception.");
+ });
+ },
+ "promise_test with unhandled exception in reject reaction (should FAIL)");
+</script>
diff --git a/testing/web-platform/tests/resources/examples/apisample14.html b/testing/web-platform/tests/resources/examples/apisample14.html
new file mode 100644
index 000000000..89803f0bb
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample14.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Dedicated Worker Tests</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+</head>
+<body>
+<h1>Dedicated Web Worker Tests</h1>
+<p>Demonstrates running <tt>testharness</tt> based tests inside a dedicated web worker.
+<p>The test harness is expected to fail due to an uncaught exception in one worker.</p>
+<div id="log"></div>
+
+<script>
+test(function(t) {
+ assert_true("Worker" in self, "Browser should support Workers");
+ },
+ "Browser supports Workers");
+
+fetch_tests_from_worker(new Worker("apisample-worker.js"));
+
+fetch_tests_from_worker(new Worker("apisample-error-worker.js"));
+
+test(function(t) {
+ assert_false(false, "False is false");
+ },
+ "Test running on main document.");
+</script>
+</body>
diff --git a/testing/web-platform/tests/resources/examples/apisample15.html b/testing/web-platform/tests/resources/examples/apisample15.html
new file mode 100644
index 000000000..631d1922b
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample15.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with a shared worker</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+</head>
+<body>
+<h1>Shared Web Worker Tests</h1>
+<p>Demonstrates running <tt>testharness</tt> based tests inside a shared worker.
+<p>The test harness should time out due to one of the tests in the worker timing out.
+<p>This test assumes that the browser supports <a href="http://www.w3.org/TR/workers/#shared-workers-and-the-sharedworker-interface">shared web workers</a>.
+<div id="log"></div>
+
+<script>
+test(
+ function(t) {
+ assert_true("SharedWorker" in self,
+ "Browser should support SharedWorkers");
+ },
+ "Browser supports SharedWorkers");
+
+fetch_tests_from_worker(new SharedWorker("apisample-worker.js",
+ "My shared worker"));
+</script>
+</body>
diff --git a/testing/web-platform/tests/resources/examples/apisample16.html b/testing/web-platform/tests/resources/examples/apisample16.html
new file mode 100644
index 000000000..d859d94bf
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample16.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with a service worker</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+</head>
+<body>
+<h1>Service Worker Tests</h1>
+<p>Demonstrates running <tt>testharness</tt> based tests inside a service worker.
+<p>The test harness should time out due to one of the tests inside the worker timing out.
+<p>This test assumes that the browser supports <a href="http://www.w3.org/TR/service-workers/">ServiceWorkers</a>.
+<div id="log"></div>
+
+<script>
+test(
+ function(t) {
+ assert_true("serviceWorker" in navigator,
+ "navigator.serviceWorker exists");
+ },
+ "Browser supports ServiceWorker");
+
+promise_test(
+ function() {
+ // Since the service worker registration could be in an indeterminate
+ // state (due to, for example, a previous test run failing), we start by
+ // unregstering our service worker and then registering it again.
+ var scope = "/service-worker-scope";
+ var worker_url = "apisample-worker.js";
+
+ return navigator.serviceWorker.register(worker_url, {scope: scope})
+ .then(
+ function(registration) {
+ return registration.unregister();
+ })
+ .then(
+ function() {
+ return navigator.serviceWorker.register(worker_url, {scope: scope});
+ })
+ .then(
+ function(registration) {
+ add_completion_callback(
+ function() {
+ registration.unregister();
+ });
+
+ return new Promise(
+ function(resolve) {
+ registration.addEventListener("updatefound",
+ function() {
+ resolve(registration.installing);
+ });
+ });
+ })
+ .then(
+ function(worker) {
+ fetch_tests_from_worker(worker);
+ });
+ },
+ "Register ServiceWorker");
+</script>
+</body>
diff --git a/testing/web-platform/tests/resources/examples/apisample17.html b/testing/web-platform/tests/resources/examples/apisample17.html
new file mode 100644
index 000000000..c27c417b8
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample17.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample for using generate_tests to create a series of tests that share the same callback.</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+</head>
+<body>
+<script>
+// generate_tests takes an array of arrays that define tests
+// but lets pass it an empty array and verify it does nothing.
+function null_callback() {
+ throw "null_callback should not be called.";
+}
+generate_tests(null_callback, []);
+
+// Generate 3 tests specifying the name and one parameter
+function validate_arguments(arg1) {
+ assert_equals(arg1, 1, "Ensure that we get our expected argument");
+}
+generate_tests(validate_arguments, [
+ ["first test", 1],
+ ["second test", 1],
+ ["third test", 1],
+]);
+
+// Generate a test passing in a properties object that is shared across tests.
+function validate_properties() {
+ assert_true(this.properties.sentinel, "Ensure that we got the right properties object.");
+}
+generate_tests(validate_properties, [["sentinel check 1"], ["sentinel check 2"]], {sentinel: true});
+
+// Generate a test passing in a properties object that is shared across tests.
+function validate_separate_properties() {
+ if (this.name === "sentinel check 1 unique properties") {
+ assert_true(this.properties.sentinel, "Ensure that we got the right properties object. Expect sentinel: true.");
+ }
+ else {
+ assert_false(this.properties.sentinel, "Ensure that we got the right properties object. Expect sentinel: false.");
+ }
+}
+generate_tests(validate_separate_properties, [["sentinel check 1 unique properties"], ["sentinel check 2 unique properties"]], [{sentinel: true}, {sentinel: false}]);
+
+// Finally generate a complicated set of tests from another data source
+var letters = ["a", "b", "c", "d", "e", "f"];
+var numbers = [0, 1, 2, 3, 4, 5];
+function validate_related_arguments(arg1, arg2) {
+ assert_equals(arg1.charCodeAt(0) - "a".charCodeAt(0), arg2, "Ensure that we can map letters to numbers.");
+}
+function format_as_test(letter, index, letters) {
+ return ["Test to map " + letter + " to " + numbers[index], letter, numbers[index]];
+}
+generate_tests(validate_related_arguments, letters.map(format_as_test));
+</script>
+</body>
+</html>
+
+
+
diff --git a/testing/web-platform/tests/resources/examples/apisample2.htm b/testing/web-platform/tests/resources/examples/apisample2.htm
new file mode 100644
index 000000000..4a4c16b4d
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample2.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample HTML5 API Tests</title>
+</head>
+<body onload="load_test_attr.done()">
+<h1>Sample HTML5 API Tests</h1>
+<p>There should be two results</p>
+<div id="log"></div>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+setup({explicit_done:true})
+test(function() {assert_true(true)}, "Test defined before onload");
+
+onload = function() {test(function (){assert_true(true)}, "Test defined after onload");
+done();
+}
+</script>
diff --git a/testing/web-platform/tests/resources/examples/apisample3.htm b/testing/web-platform/tests/resources/examples/apisample3.htm
new file mode 100644
index 000000000..4dbbf9a87
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample3.htm
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample HTML5 API Tests</title>
+</head>
+<script src="../testharness.js"></script>
+
+<body onload="load_test_attr.done()">
+<h1>Sample HTML5 API Tests</h1>
+<div id="log"></div>
+<script>
+setup({explicit_timeout:true});
+var t = async_test("This test should give a status of 'Not Run' without a delay");
+timeout();
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/resources/examples/apisample4.htm b/testing/web-platform/tests/resources/examples/apisample4.htm
new file mode 100644
index 000000000..c8fbbded6
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample4.htm
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Harness Handling Uncaught Exception</title>
+</head>
+<script src="../testharness.js"></script>
+
+<body>
+<h1>Harness Handling Uncaught Exception</h1>
+<div id="log"></div>
+<script>
+var t = async_test("This should show a harness status of 'Error' and a test status of 'Not Run'");
+throw new Error("Example Error");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/resources/examples/apisample5.htm b/testing/web-platform/tests/resources/examples/apisample5.htm
new file mode 100644
index 000000000..3edf602a1
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample5.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Harness Ignoring Uncaught Exception</title>
+</head>
+<script src="../testharness.js"></script>
+
+<body>
+<h1>Harness Ignoring Uncaught Exception</h1>
+<div id="log"></div>
+<script>
+setup({allow_uncaught_exception:true});
+var t = async_test("setup({allow_uncaught_exception:true}) should allow tests to pass even if there is an exception");
+onerror = t.step_func(function() {t.done()});
+throw new Error("Example Error");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/resources/examples/apisample6.html b/testing/web-platform/tests/resources/examples/apisample6.html
new file mode 100644
index 000000000..7459c54d5
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample6.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Example with file_is_test</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+onload = function() {
+ assert_true(true);
+ done();
+}
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/examples/apisample7.html b/testing/web-platform/tests/resources/examples/apisample7.html
new file mode 100644
index 000000000..6885f52f8
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample7.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Example with file_is_test (should fail)</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+onload = function() {
+ assert_true(false);
+ done();
+}
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/examples/apisample8.html b/testing/web-platform/tests/resources/examples/apisample8.html
new file mode 100644
index 000000000..70853d9c6
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample8.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<title>Example single page test with no body</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+assert_true(true);
+done();
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/examples/apisample9.html b/testing/web-platform/tests/resources/examples/apisample9.html
new file mode 100644
index 000000000..f84433dd1
--- /dev/null
+++ b/testing/web-platform/tests/resources/examples/apisample9.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<title>Example single page test with no asserts</title>
+<script src="../testharness.js"></script>
+<script src="../testharnessreport.js"></script>
+<script>
+done();
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/idlharness.js b/testing/web-platform/tests/resources/idlharness.js
new file mode 100644
index 000000000..608964659
--- /dev/null
+++ b/testing/web-platform/tests/resources/idlharness.js
@@ -0,0 +1,1853 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+/* For user documentation see docs/idlharness.md */
+
+/**
+ * Notes for people who want to edit this file (not just use it as a library):
+ *
+ * Most of the interesting stuff happens in the derived classes of IdlObject,
+ * especially IdlInterface. The entry point for all IdlObjects is .test(),
+ * which is called by IdlArray.test(). An IdlObject is conceptually just
+ * "thing we want to run tests on", and an IdlArray is an array of IdlObjects
+ * with some additional data thrown in.
+ *
+ * The object model is based on what WebIDLParser.js produces, which is in turn
+ * based on its pegjs grammar. If you want to figure out what properties an
+ * object will have from WebIDLParser.js, the best way is to look at the
+ * grammar:
+ *
+ * https://github.com/darobin/webidl.js/blob/master/lib/grammar.peg
+ *
+ * So for instance:
+ *
+ * // interface definition
+ * interface
+ * = extAttrs:extendedAttributeList? S? "interface" S name:identifier w herit:ifInheritance? w "{" w mem:ifMember* w "}" w ";" w
+ * { return { type: "interface", name: name, inheritance: herit, members: mem, extAttrs: extAttrs }; }
+ *
+ * This means that an "interface" object will have a .type property equal to
+ * the string "interface", a .name property equal to the identifier that the
+ * parser found, an .inheritance property equal to either null or the result of
+ * the "ifInheritance" production found elsewhere in the grammar, and so on.
+ * After each grammatical production is a JavaScript function in curly braces
+ * that gets called with suitable arguments and returns some JavaScript value.
+ *
+ * (Note that the version of WebIDLParser.js we use might sometimes be
+ * out-of-date or forked.)
+ *
+ * The members and methods of the classes defined by this file are all at least
+ * briefly documented, hopefully.
+ */
+(function(){
+"use strict";
+/// Helpers ///
+function constValue (cnt) {
+ if (cnt.type === "null") return null;
+ if (cnt.type === "NaN") return NaN;
+ if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;
+ return cnt.value;
+}
+
+function minOverloadLength(overloads) {
+ if (!overloads.length) {
+ return 0;
+ }
+
+ return overloads.map(function(attr) {
+ return attr.arguments ? attr.arguments.filter(function(arg) {
+ return !arg.optional && !arg.variadic;
+ }).length : 0;
+ })
+ .reduce(function(m, n) { return Math.min(m, n); });
+}
+
+function throwOrReject(a_test, operation, fn, obj, args, message, cb) {
+ if (operation.idlType.generic !== "Promise") {
+ assert_throws(new TypeError(), function() {
+ fn.apply(obj, args);
+ }, message);
+ cb();
+ } else {
+ try {
+ promise_rejects(a_test, new TypeError(), fn.apply(obj, args)).then(cb, cb);
+ } catch (e){
+ a_test.step(function() {
+ assert_unreached("Throws \"" + e + "\" instead of rejecting promise");
+ cb();
+ });
+ }
+ }
+}
+
+function awaitNCallbacks(n, cb, ctx) {
+ var counter = 0;
+ return function() {
+ counter++;
+ if (counter >= n) {
+ cb();
+ }
+ };
+}
+
+var fround = (function(){
+ if (Math.fround) return Math.fround;
+
+ var arr = new Float32Array(1);
+ return function fround(n) {
+ arr[0] = n;
+ return arr[0];
+ };
+})();
+
+/// IdlArray ///
+// Entry point
+self.IdlArray = function()
+//@{
+{
+ /**
+ * A map from strings to the corresponding named IdlObject, such as
+ * IdlInterface or IdlException. These are the things that test() will run
+ * tests on.
+ */
+ this.members = {};
+
+ /**
+ * A map from strings to arrays of strings. The keys are interface or
+ * exception names, and are expected to also exist as keys in this.members
+ * (otherwise they'll be ignored). This is populated by add_objects() --
+ * see documentation at the start of the file. The actual tests will be
+ * run by calling this.members[name].test_object(obj) for each obj in
+ * this.objects[name]. obj is a string that will be eval'd to produce a
+ * JavaScript value, which is supposed to be an object implementing the
+ * given IdlObject (interface, exception, etc.).
+ */
+ this.objects = {};
+
+ /**
+ * When adding multiple collections of IDLs one at a time, an earlier one
+ * might contain a partial interface or implements statement that depends
+ * on a later one. Save these up and handle them right before we run
+ * tests.
+ *
+ * .partials is simply an array of objects from WebIDLParser.js'
+ * "partialinterface" production. .implements maps strings to arrays of
+ * strings, such that
+ *
+ * A implements B;
+ * A implements C;
+ * D implements E;
+ *
+ * results in { A: ["B", "C"], D: ["E"] }.
+ */
+ this.partials = [];
+ this["implements"] = {};
+};
+
+//@}
+IdlArray.prototype.add_idls = function(raw_idls)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ this.internal_add_idls(WebIDL2.parse(raw_idls));
+};
+
+//@}
+IdlArray.prototype.add_untested_idls = function(raw_idls)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ var parsed_idls = WebIDL2.parse(raw_idls);
+ for (var i = 0; i < parsed_idls.length; i++)
+ {
+ parsed_idls[i].untested = true;
+ if ("members" in parsed_idls[i])
+ {
+ for (var j = 0; j < parsed_idls[i].members.length; j++)
+ {
+ parsed_idls[i].members[j].untested = true;
+ }
+ }
+ }
+ this.internal_add_idls(parsed_idls);
+};
+
+//@}
+IdlArray.prototype.internal_add_idls = function(parsed_idls)
+//@{
+{
+ /**
+ * Internal helper called by add_idls() and add_untested_idls().
+ * parsed_idls is an array of objects that come from WebIDLParser.js's
+ * "definitions" production. The add_untested_idls() entry point
+ * additionally sets an .untested property on each object (and its
+ * .members) so that they'll be skipped by test() -- they'll only be
+ * used for base interfaces of tested interfaces, return types, etc.
+ */
+ parsed_idls.forEach(function(parsed_idl)
+ {
+ if (parsed_idl.type == "interface" && parsed_idl.partial)
+ {
+ this.partials.push(parsed_idl);
+ return;
+ }
+
+ if (parsed_idl.type == "implements")
+ {
+ if (!(parsed_idl.target in this["implements"]))
+ {
+ this["implements"][parsed_idl.target] = [];
+ }
+ this["implements"][parsed_idl.target].push(parsed_idl["implements"]);
+ return;
+ }
+
+ parsed_idl.array = this;
+ if (parsed_idl.name in this.members)
+ {
+ throw "Duplicate identifier " + parsed_idl.name;
+ }
+ switch(parsed_idl.type)
+ {
+ case "interface":
+ this.members[parsed_idl.name] =
+ new IdlInterface(parsed_idl, /* is_callback = */ false);
+ break;
+
+ case "dictionary":
+ // Nothing to test, but we need the dictionary info around for type
+ // checks
+ this.members[parsed_idl.name] = new IdlDictionary(parsed_idl);
+ break;
+
+ case "typedef":
+ this.members[parsed_idl.name] = new IdlTypedef(parsed_idl);
+ break;
+
+ case "callback":
+ // TODO
+ console.log("callback not yet supported");
+ break;
+
+ case "enum":
+ this.members[parsed_idl.name] = new IdlEnum(parsed_idl);
+ break;
+
+ case "callback interface":
+ this.members[parsed_idl.name] =
+ new IdlInterface(parsed_idl, /* is_callback = */ true);
+ break;
+
+ default:
+ throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported";
+ }
+ }.bind(this));
+};
+
+//@}
+IdlArray.prototype.add_objects = function(dict)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ for (var k in dict)
+ {
+ if (k in this.objects)
+ {
+ this.objects[k] = this.objects[k].concat(dict[k]);
+ }
+ else
+ {
+ this.objects[k] = dict[k];
+ }
+ }
+};
+
+//@}
+IdlArray.prototype.prevent_multiple_testing = function(name)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ this.members[name].prevent_multiple_testing = true;
+};
+
+//@}
+IdlArray.prototype.recursively_get_implements = function(interface_name)
+//@{
+{
+ /**
+ * Helper function for test(). Returns an array of things that implement
+ * interface_name, so if the IDL contains
+ *
+ * A implements B;
+ * B implements C;
+ * B implements D;
+ *
+ * then recursively_get_implements("A") should return ["B", "C", "D"].
+ */
+ var ret = this["implements"][interface_name];
+ if (ret === undefined)
+ {
+ return [];
+ }
+ for (var i = 0; i < this["implements"][interface_name].length; i++)
+ {
+ ret = ret.concat(this.recursively_get_implements(ret[i]));
+ if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
+ {
+ throw "Circular implements statements involving " + ret[i];
+ }
+ }
+ return ret;
+};
+
+function exposed_in(globals) {
+ if ('document' in self) {
+ return globals.indexOf("Window") >= 0;
+ }
+ if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ return globals.indexOf("Worker") >= 0 ||
+ globals.indexOf("DedicatedWorker") >= 0;
+ }
+ if ('SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ return globals.indexOf("Worker") >= 0 ||
+ globals.indexOf("SharedWorker") >= 0;
+ }
+ if ('ServiceWorkerGlobalScope' in self &&
+ self instanceof ServiceWorkerGlobalScope) {
+ return globals.indexOf("Worker") >= 0 ||
+ globals.indexOf("ServiceWorker") >= 0;
+ }
+ throw "Unexpected global object";
+}
+
+//@}
+IdlArray.prototype.test = function()
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+
+ // First merge in all the partial interfaces and implements statements we
+ // encountered.
+ this.partials.forEach(function(parsed_idl)
+ {
+ if (!(parsed_idl.name in this.members)
+ || !(this.members[parsed_idl.name] instanceof IdlInterface))
+ {
+ throw "Partial interface " + parsed_idl.name + " with no original interface";
+ }
+ if (parsed_idl.extAttrs)
+ {
+ parsed_idl.extAttrs.forEach(function(extAttr)
+ {
+ this.members[parsed_idl.name].extAttrs.push(extAttr);
+ }.bind(this));
+ }
+ parsed_idl.members.forEach(function(member)
+ {
+ this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
+ }.bind(this));
+ }.bind(this));
+ this.partials = [];
+
+ for (var lhs in this["implements"])
+ {
+ this.recursively_get_implements(lhs).forEach(function(rhs)
+ {
+ var errStr = lhs + " implements " + rhs + ", but ";
+ if (!(lhs in this.members)) throw errStr + lhs + " is undefined.";
+ if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface.";
+ if (!(rhs in this.members)) throw errStr + rhs + " is undefined.";
+ if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface.";
+ this.members[rhs].members.forEach(function(member)
+ {
+ this.members[lhs].members.push(new IdlInterfaceMember(member));
+ }.bind(this));
+ }.bind(this));
+ }
+ this["implements"] = {};
+
+ Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
+ var member = this.members[memberName];
+ if (!(member instanceof IdlInterface)) {
+ return;
+ }
+
+ var exposed = member.extAttrs.filter(function(a) { return a.name == "Exposed" });
+ if (exposed.length > 1) {
+ throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed;
+ }
+
+ var globals = exposed.length === 1
+ ? exposed[0].rhs.value
+ : ["Window"];
+ member.exposed = exposed_in(globals);
+ }.bind(this));
+
+ // Now run test() on every member, and test_object() for every object.
+ for (var name in this.members)
+ {
+ this.members[name].test();
+ if (name in this.objects)
+ {
+ this.objects[name].forEach(function(str)
+ {
+ this.members[name].test_object(str);
+ }.bind(this));
+ }
+ }
+};
+
+//@}
+IdlArray.prototype.assert_type_is = function(value, type)
+//@{
+{
+ /**
+ * Helper function that tests that value is an instance of type according
+ * to the rules of WebIDL. value is any JavaScript value, and type is an
+ * object produced by WebIDLParser.js' "type" production. That production
+ * is fairly elaborate due to the complexity of WebIDL's types, so it's
+ * best to look at the grammar to figure out what properties it might have.
+ */
+ if (type.idlType == "any")
+ {
+ // No assertions to make
+ return;
+ }
+
+ if (type.nullable && value === null)
+ {
+ // This is fine
+ return;
+ }
+
+ if (type.array)
+ {
+ // TODO: not supported yet
+ return;
+ }
+
+ if (type.sequence)
+ {
+ assert_true(Array.isArray(value), "is not array");
+ if (!value.length)
+ {
+ // Nothing we can do.
+ return;
+ }
+ this.assert_type_is(value[0], type.idlType.idlType);
+ return;
+ }
+
+ type = type.idlType;
+
+ switch(type)
+ {
+ case "void":
+ assert_equals(value, undefined);
+ return;
+
+ case "boolean":
+ assert_equals(typeof value, "boolean");
+ return;
+
+ case "byte":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(-128 <= value && value <= 127, "byte " + value + " not in range [-128, 127]");
+ return;
+
+ case "octet":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(0 <= value && value <= 255, "octet " + value + " not in range [0, 255]");
+ return;
+
+ case "short":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(-32768 <= value && value <= 32767, "short " + value + " not in range [-32768, 32767]");
+ return;
+
+ case "unsigned short":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(0 <= value && value <= 65535, "unsigned short " + value + " not in range [0, 65535]");
+ return;
+
+ case "long":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(-2147483648 <= value && value <= 2147483647, "long " + value + " not in range [-2147483648, 2147483647]");
+ return;
+
+ case "unsigned long":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(0 <= value && value <= 4294967295, "unsigned long " + value + " not in range [0, 4294967295]");
+ return;
+
+ case "long long":
+ assert_equals(typeof value, "number");
+ return;
+
+ case "unsigned long long":
+ case "DOMTimeStamp":
+ assert_equals(typeof value, "number");
+ assert_true(0 <= value, "unsigned long long is negative");
+ return;
+
+ case "float":
+ assert_equals(typeof value, "number");
+ assert_equals(value, fround(value), "float rounded to 32-bit float should be itself");
+ assert_not_equals(value, Infinity);
+ assert_not_equals(value, -Infinity);
+ assert_not_equals(value, NaN);
+ return;
+
+ case "DOMHighResTimeStamp":
+ case "double":
+ assert_equals(typeof value, "number");
+ assert_not_equals(value, Infinity);
+ assert_not_equals(value, -Infinity);
+ assert_not_equals(value, NaN);
+ return;
+
+ case "unrestricted float":
+ assert_equals(typeof value, "number");
+ assert_equals(value, fround(value), "unrestricted float rounded to 32-bit float should be itself");
+ return;
+
+ case "unrestricted double":
+ assert_equals(typeof value, "number");
+ return;
+
+ case "DOMString":
+ assert_equals(typeof value, "string");
+ return;
+
+ case "ByteString":
+ assert_equals(typeof value, "string");
+ assert_regexp_match(value, /^[\x00-\x7F]*$/);
+ return;
+
+ case "USVString":
+ assert_equals(typeof value, "string");
+ assert_regexp_match(value, /^([\x00-\ud7ff\ue000-\uffff]|[\ud800-\udbff][\udc00-\udfff])*$/);
+ return;
+
+ case "object":
+ assert_true(typeof value == "object" || typeof value == "function", "wrong type: not object or function");
+ return;
+ }
+
+ if (!(type in this.members))
+ {
+ throw "Unrecognized type " + type;
+ }
+
+ if (this.members[type] instanceof IdlInterface)
+ {
+ // We don't want to run the full
+ // IdlInterface.prototype.test_instance_of, because that could result
+ // in an infinite loop. TODO: This means we don't have tests for
+ // NoInterfaceObject interfaces, and we also can't test objects that
+ // come from another self.
+ assert_true(typeof value == "object" || typeof value == "function", "wrong type: not object or function");
+ if (value instanceof Object
+ && !this.members[type].has_extended_attribute("NoInterfaceObject")
+ && type in self)
+ {
+ assert_true(value instanceof self[type], "not instanceof " + type);
+ }
+ }
+ else if (this.members[type] instanceof IdlEnum)
+ {
+ assert_equals(typeof value, "string");
+ }
+ else if (this.members[type] instanceof IdlDictionary)
+ {
+ // TODO: Test when we actually have something to test this on
+ }
+ else if (this.members[type] instanceof IdlTypedef)
+ {
+ // TODO: Test when we actually have something to test this on
+ }
+ else
+ {
+ throw "Type " + type + " isn't an interface or dictionary";
+ }
+};
+//@}
+
+/// IdlObject ///
+function IdlObject() {}
+IdlObject.prototype.test = function()
+//@{
+{
+ /**
+ * By default, this does nothing, so no actual tests are run for IdlObjects
+ * that don't define any (e.g., IdlDictionary at the time of this writing).
+ */
+};
+
+//@}
+IdlObject.prototype.has_extended_attribute = function(name)
+//@{
+{
+ /**
+ * This is only meaningful for things that support extended attributes,
+ * such as interfaces, exceptions, and members.
+ */
+ return this.extAttrs.some(function(o)
+ {
+ return o.name == name;
+ });
+};
+
+//@}
+
+/// IdlDictionary ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlDictionary(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "dictionary"
+ * production.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** An array of objects produced by the "dictionaryMember" production. */
+ this.members = obj.members;
+
+ /**
+ * The name (as a string) of the dictionary type we inherit from, or null
+ * if there is none.
+ */
+ this.base = obj.inheritance;
+}
+
+//@}
+IdlDictionary.prototype = Object.create(IdlObject.prototype);
+
+/// IdlInterface ///
+function IdlInterface(obj, is_callback) {
+ /**
+ * obj is an object produced by the WebIDLParser.js "interface" production.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** A back-reference to our IdlArray. */
+ this.array = obj.array;
+
+ /**
+ * An indicator of whether we should run tests on the interface object and
+ * interface prototype object. Tests on members are controlled by .untested
+ * on each member, not this.
+ */
+ this.untested = obj.untested;
+
+ /** An array of objects produced by the "ExtAttr" production. */
+ this.extAttrs = obj.extAttrs;
+
+ /** An array of IdlInterfaceMembers. */
+ this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });
+ if (this.has_extended_attribute("Unforgeable")) {
+ this.members
+ .filter(function(m) { return !m["static"] && (m.type == "attribute" || m.type == "operation"); })
+ .forEach(function(m) { return m.isUnforgeable = true; });
+ }
+
+ /**
+ * The name (as a string) of the type we inherit from, or null if there is
+ * none.
+ */
+ this.base = obj.inheritance;
+
+ this._is_callback = is_callback;
+}
+IdlInterface.prototype = Object.create(IdlObject.prototype);
+IdlInterface.prototype.is_callback = function()
+//@{
+{
+ return this._is_callback;
+};
+//@}
+
+IdlInterface.prototype.has_constants = function()
+//@{
+{
+ return this.members.some(function(member) {
+ return member.type === "const";
+ });
+};
+//@}
+
+IdlInterface.prototype.is_global = function()
+//@{
+{
+ return this.extAttrs.some(function(attribute) {
+ return attribute.name === "Global" ||
+ attribute.name === "PrimaryGlobal";
+ });
+};
+//@}
+
+IdlInterface.prototype.test = function()
+//@{
+{
+ if (this.has_extended_attribute("NoInterfaceObject"))
+ {
+ // No tests to do without an instance. TODO: We should still be able
+ // to run tests on the prototype object, if we obtain one through some
+ // other means.
+ return;
+ }
+
+ if (!this.exposed) {
+ test(function() {
+ assert_false(this.name in self);
+ }.bind(this), this.name + " interface: existence and properties of interface object");
+ return;
+ }
+
+ if (!this.untested)
+ {
+ // First test things to do with the exception/interface object and
+ // exception/interface prototype object.
+ this.test_self();
+ }
+ // Then test things to do with its members (constants, fields, attributes,
+ // operations, . . .). These are run even if .untested is true, because
+ // members might themselves be marked as .untested. This might happen to
+ // interfaces if the interface itself is untested but a partial interface
+ // that extends it is tested -- then the interface itself and its initial
+ // members will be marked as untested, but the members added by the partial
+ // interface are still tested.
+ this.test_members();
+};
+//@}
+
+IdlInterface.prototype.test_self = function()
+//@{
+{
+ test(function()
+ {
+ // This function tests WebIDL as of 2015-01-13.
+
+ // "For every interface that is exposed in a given ECMAScript global
+ // environment and:
+ // * is a callback interface that has constants declared on it, or
+ // * is a non-callback interface that is not declared with the
+ // [NoInterfaceObject] extended attribute,
+ // a corresponding property MUST exist on the ECMAScript global object.
+ // The name of the property is the identifier of the interface, and its
+ // value is an object called the interface object.
+ // The property has the attributes { [[Writable]]: true,
+ // [[Enumerable]]: false, [[Configurable]]: true }."
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ // TODO: Should we test here that the property is actually writable
+ // etc., or trust getOwnPropertyDescriptor?
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+ var desc = Object.getOwnPropertyDescriptor(self, this.name);
+ assert_false("get" in desc, "self's property " + format_value(this.name) + " has getter");
+ assert_false("set" in desc, "self's property " + format_value(this.name) + " has setter");
+ assert_true(desc.writable, "self's property " + format_value(this.name) + " is not writable");
+ assert_false(desc.enumerable, "self's property " + format_value(this.name) + " is enumerable");
+ assert_true(desc.configurable, "self's property " + format_value(this.name) + " is not configurable");
+
+ if (this.is_callback()) {
+ // "The internal [[Prototype]] property of an interface object for
+ // a callback interface MUST be the Object.prototype object."
+ assert_equals(Object.getPrototypeOf(self[this.name]), Object.prototype,
+ "prototype of self's property " + format_value(this.name) + " is not Object.prototype");
+
+ return;
+ }
+
+ // "The interface object for a given non-callback interface is a
+ // function object."
+ // "If an object is defined to be a function object, then it has
+ // characteristics as follows:"
+
+ // Its [[Prototype]] internal property is otherwise specified (see
+ // below).
+
+ // "* Its [[Get]] internal property is set as described in ECMA-262
+ // section 9.1.8."
+ // Not much to test for this.
+
+ // "* Its [[Construct]] internal property is set as described in
+ // ECMA-262 section 19.2.2.3."
+ // Tested below if no constructor is defined. TODO: test constructors
+ // if defined.
+
+ // "* Its @@hasInstance property is set as described in ECMA-262
+ // section 19.2.3.8, unless otherwise specified."
+ // TODO
+
+ // ES6 (rev 30) 19.1.3.6:
+ // "Else, if O has a [[Call]] internal method, then let builtinTag be
+ // "Function"."
+ assert_class_string(self[this.name], "Function", "class string of " + this.name);
+
+ // "The [[Prototype]] internal property of an interface object for a
+ // non-callback interface is determined as follows:"
+ var prototype = Object.getPrototypeOf(self[this.name]);
+ if (this.base) {
+ // "* If the interface inherits from some other interface, the
+ // value of [[Prototype]] is the interface object for that other
+ // interface."
+ var has_interface_object =
+ !this.array
+ .members[this.base]
+ .has_extended_attribute("NoInterfaceObject");
+ if (has_interface_object) {
+ assert_own_property(self, this.base,
+ 'should inherit from ' + this.base +
+ ', but self has no such property');
+ assert_equals(prototype, self[this.base],
+ 'prototype of ' + this.name + ' is not ' +
+ this.base);
+ }
+ } else {
+ // "If the interface doesn't inherit from any other interface, the
+ // value of [[Prototype]] is %FunctionPrototype% ([ECMA-262],
+ // section 6.1.7.4)."
+ assert_equals(prototype, Function.prototype,
+ "prototype of self's property " + format_value(this.name) + " is not Function.prototype");
+ }
+
+ if (!this.has_extended_attribute("Constructor")) {
+ // "The internal [[Call]] method of the interface object behaves as
+ // follows . . .
+ //
+ // "If I was not declared with a [Constructor] extended attribute,
+ // then throw a TypeError."
+ assert_throws(new TypeError(), function() {
+ self[this.name]();
+ }.bind(this), "interface object didn't throw TypeError when called as a function");
+ assert_throws(new TypeError(), function() {
+ new self[this.name]();
+ }.bind(this), "interface object didn't throw TypeError when called as a constructor");
+ }
+ }.bind(this), this.name + " interface: existence and properties of interface object");
+
+ if (!this.is_callback()) {
+ test(function() {
+ // This function tests WebIDL as of 2014-10-25.
+ // https://heycam.github.io/webidl/#es-interface-call
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ // "Interface objects for non-callback interfaces MUST have a
+ // property named “length” with attributes { [[Writable]]: false,
+ // [[Enumerable]]: false, [[Configurable]]: true } whose value is
+ // a Number."
+ assert_own_property(self[this.name], "length");
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], "length");
+ assert_false("get" in desc, this.name + ".length has getter");
+ assert_false("set" in desc, this.name + ".length has setter");
+ assert_false(desc.writable, this.name + ".length is writable");
+ assert_false(desc.enumerable, this.name + ".length is enumerable");
+ assert_true(desc.configurable, this.name + ".length is not configurable");
+
+ var constructors = this.extAttrs
+ .filter(function(attr) { return attr.name == "Constructor"; });
+ var expected_length = minOverloadLength(constructors);
+ assert_equals(self[this.name].length, expected_length, "wrong value for " + this.name + ".length");
+ }.bind(this), this.name + " interface object length");
+ }
+
+ if (!this.is_callback() || this.has_constants()) {
+ test(function() {
+ // This function tests WebIDL as of 2015-11-17.
+ // https://heycam.github.io/webidl/#interface-object
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ // "All interface objects must have a property named “name” with
+ // attributes { [[Writable]]: false, [[Enumerable]]: false,
+ // [[Configurable]]: true } whose value is the identifier of the
+ // corresponding interface."
+
+ assert_own_property(self[this.name], "name");
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], "name");
+ assert_false("get" in desc, this.name + ".name has getter");
+ assert_false("set" in desc, this.name + ".name has setter");
+ assert_false(desc.writable, this.name + ".name is writable");
+ assert_false(desc.enumerable, this.name + ".name is enumerable");
+ assert_true(desc.configurable, this.name + ".name is not configurable");
+ assert_equals(self[this.name].name, this.name, "wrong value for " + this.name + ".name");
+ }.bind(this), this.name + " interface object name");
+ }
+
+ // TODO: Test named constructors if I find any interfaces that have them.
+
+ test(function()
+ {
+ // This function tests WebIDL as of 2015-01-21.
+ // https://heycam.github.io/webidl/#interface-object
+
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ // "An interface object for a non-callback interface must have a
+ // property named “prototype” with attributes { [[Writable]]: false,
+ // [[Enumerable]]: false, [[Configurable]]: false } whose value is an
+ // object called the interface prototype object. This object has
+ // properties that correspond to the regular attributes and regular
+ // operations defined on the interface, and is described in more detail
+ // in section 4.5.4 below."
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], "prototype");
+ assert_false("get" in desc, this.name + ".prototype has getter");
+ assert_false("set" in desc, this.name + ".prototype has setter");
+ assert_false(desc.writable, this.name + ".prototype is writable");
+ assert_false(desc.enumerable, this.name + ".prototype is enumerable");
+ assert_false(desc.configurable, this.name + ".prototype is configurable");
+
+ // Next, test that the [[Prototype]] of the interface prototype object
+ // is correct. (This is made somewhat difficult by the existence of
+ // [NoInterfaceObject].)
+ // TODO: Aryeh thinks there's at least other place in this file where
+ // we try to figure out if an interface prototype object is
+ // correct. Consolidate that code.
+
+ // "The interface prototype object for a given interface A must have an
+ // internal [[Prototype]] property whose value is returned from the
+ // following steps:
+ // "If A is declared with the [Global] or [PrimaryGlobal] extended
+ // attribute, and A supports named properties, then return the named
+ // properties object for A, as defined in section 4.5.5 below.
+ // "Otherwise, if A is declared to inherit from another interface, then
+ // return the interface prototype object for the inherited interface.
+ // "Otherwise, if A is declared with the [ArrayClass] extended
+ // attribute, then return %ArrayPrototype% ([ECMA-262], section
+ // 6.1.7.4).
+ // "Otherwise, return %ObjectPrototype% ([ECMA-262], section 6.1.7.4).
+ // ([ECMA-262], section 15.2.4).
+ if (this.name === "Window") {
+ assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
+ 'WindowProperties',
+ 'Class name for prototype of Window' +
+ '.prototype is not "WindowProperties"');
+ } else {
+ var inherit_interface, inherit_interface_has_interface_object;
+ if (this.base) {
+ inherit_interface = this.base;
+ inherit_interface_has_interface_object =
+ !this.array
+ .members[inherit_interface]
+ .has_extended_attribute("NoInterfaceObject");
+ } else if (this.has_extended_attribute('ArrayClass')) {
+ inherit_interface = 'Array';
+ inherit_interface_has_interface_object = true;
+ } else {
+ inherit_interface = 'Object';
+ inherit_interface_has_interface_object = true;
+ }
+ if (inherit_interface_has_interface_object) {
+ assert_own_property(self, inherit_interface,
+ 'should inherit from ' + inherit_interface + ', but self has no such property');
+ assert_own_property(self[inherit_interface], 'prototype',
+ 'should inherit from ' + inherit_interface + ', but that object has no "prototype" property');
+ assert_equals(Object.getPrototypeOf(self[this.name].prototype),
+ self[inherit_interface].prototype,
+ 'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype');
+ } else {
+ // We can't test that we get the correct object, because this is the
+ // only way to get our hands on it. We only test that its class
+ // string, at least, is correct.
+ assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
+ inherit_interface + 'Prototype',
+ 'Class name for prototype of ' + this.name +
+ '.prototype is not "' + inherit_interface + 'Prototype"');
+ }
+ }
+
+ // "The class string of an interface prototype object is the
+ // concatenation of the interface’s identifier and the string
+ // “Prototype”."
+ assert_class_string(self[this.name].prototype, this.name + "Prototype",
+ "class string of " + this.name + ".prototype");
+ // String() should end up calling {}.toString if nothing defines a
+ // stringifier.
+ if (!this.has_stringifier()) {
+ assert_equals(String(self[this.name].prototype), "[object " + this.name + "Prototype]",
+ "String(" + this.name + ".prototype)");
+ }
+ }.bind(this), this.name + " interface: existence and properties of interface prototype object");
+
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // "If the [NoInterfaceObject] extended attribute was not specified on
+ // the interface, then the interface prototype object must also have a
+ // property named “constructor” with attributes { [[Writable]]: true,
+ // [[Enumerable]]: false, [[Configurable]]: true } whose value is a
+ // reference to the interface object for the interface."
+ assert_own_property(self[this.name].prototype, "constructor",
+ this.name + '.prototype does not have own property "constructor"');
+ var desc = Object.getOwnPropertyDescriptor(self[this.name].prototype, "constructor");
+ assert_false("get" in desc, this.name + ".prototype.constructor has getter");
+ assert_false("set" in desc, this.name + ".prototype.constructor has setter");
+ assert_true(desc.writable, this.name + ".prototype.constructor is not writable");
+ assert_false(desc.enumerable, this.name + ".prototype.constructor is enumerable");
+ assert_true(desc.configurable, this.name + ".prototype.constructor in not configurable");
+ assert_equals(self[this.name].prototype.constructor, self[this.name],
+ this.name + '.prototype.constructor is not the same object as ' + this.name);
+ }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property');
+};
+
+//@}
+IdlInterface.prototype.test_member_const = function(member)
+//@{
+{
+ if (!this.has_constants()) {
+ throw "Internal error: test_member_const called without any constants";
+ }
+
+ test(function()
+ {
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ // "For each constant defined on an interface A, there must be
+ // a corresponding property on the interface object, if it
+ // exists."
+ assert_own_property(self[this.name], member.name);
+ // "The value of the property is that which is obtained by
+ // converting the constant’s IDL value to an ECMAScript
+ // value."
+ assert_equals(self[this.name][member.name], constValue(member.value),
+ "property has wrong value");
+ // "The property has attributes { [[Writable]]: false,
+ // [[Enumerable]]: true, [[Configurable]]: false }."
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_false(desc.writable, "property is writable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_false(desc.configurable, "property is configurable");
+ }.bind(this), this.name + " interface: constant " + member.name + " on interface object");
+
+ // "In addition, a property with the same characteristics must
+ // exist on the interface prototype object."
+ test(function()
+ {
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ assert_own_property(self[this.name].prototype, member.name);
+ assert_equals(self[this.name].prototype[member.name], constValue(member.value),
+ "property has wrong value");
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_false(desc.writable, "property is writable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_false(desc.configurable, "property is configurable");
+ }.bind(this), this.name + " interface: constant " + member.name + " on interface prototype object");
+};
+
+
+//@}
+IdlInterface.prototype.test_member_attribute = function(member)
+//@{
+{
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ if (member["static"]) {
+ assert_own_property(self[this.name], member.name,
+ "The interface object must have a property " +
+ format_value(member.name));
+ } else if (this.is_global()) {
+ assert_own_property(self, member.name,
+ "The global object must have a property " +
+ format_value(member.name));
+ assert_false(member.name in self[this.name].prototype,
+ "The prototype object must not have a property " +
+ format_value(member.name));
+
+ var getter = Object.getOwnPropertyDescriptor(self, member.name).get;
+ assert_equals(typeof(getter), "function",
+ format_value(member.name) + " must have a getter");
+
+ // Try/catch around the get here, since it can legitimately throw.
+ // If it does, we obviously can't check for equality with direct
+ // invocation of the getter.
+ var gotValue;
+ var propVal;
+ try {
+ propVal = self[member.name];
+ gotValue = true;
+ } catch (e) {
+ gotValue = false;
+ }
+ if (gotValue) {
+ assert_equals(propVal, getter.call(undefined),
+ "Gets on a global should not require an explicit this");
+ }
+
+ this.do_interface_attribute_asserts(self, member);
+ } else {
+ assert_true(member.name in self[this.name].prototype,
+ "The prototype object must have a property " +
+ format_value(member.name));
+
+ if (!member.has_extended_attribute("LenientThis")) {
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype[member.name];
+ }.bind(this), "getting property on prototype object must throw TypeError");
+ } else {
+ assert_equals(self[this.name].prototype[member.name], undefined,
+ "getting property on prototype object must return undefined");
+ }
+ this.do_interface_attribute_asserts(self[this.name].prototype, member);
+ }
+ }.bind(this), this.name + " interface: attribute " + member.name);
+};
+
+//@}
+IdlInterface.prototype.test_member_operation = function(member)
+//@{
+{
+ var a_test = async_test(this.name + " interface: operation " + member.name +
+ "(" + member.arguments.map(
+ function(m) {return m.idlType.idlType; } )
+ +")");
+ a_test.step(function()
+ {
+ // This function tests WebIDL as of 2015-12-29.
+ // https://heycam.github.io/webidl/#es-operations
+
+ if (this.is_callback() && !this.has_constants()) {
+ a_test.done();
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ a_test.done();
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // "For each unique identifier of an exposed operation defined on the
+ // interface, there must exist a corresponding property, unless the
+ // effective overload set for that identifier and operation and with an
+ // argument count of 0 has no entries."
+
+ // TODO: Consider [Exposed].
+
+ // "The location of the property is determined as follows:"
+ var memberHolderObject;
+ // "* If the operation is static, then the property exists on the
+ // interface object."
+ if (member["static"]) {
+ assert_own_property(self[this.name], member.name,
+ "interface object missing static operation");
+ memberHolderObject = self[this.name];
+ // "* Otherwise, [...] if the interface was declared with the [Global]
+ // or [PrimaryGlobal] extended attribute, then the property exists
+ // on every object that implements the interface."
+ } else if (this.is_global()) {
+ assert_own_property(self, member.name,
+ "global object missing non-static operation");
+ memberHolderObject = self;
+ // "* Otherwise, the property exists solely on the interface’s
+ // interface prototype object."
+ } else {
+ assert_own_property(self[this.name].prototype, member.name,
+ "interface prototype object missing non-static operation");
+ memberHolderObject = self[this.name].prototype;
+ }
+ this.do_member_operation_asserts(memberHolderObject, member, a_test);
+ }.bind(this));
+};
+
+//@}
+IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject, member, a_test)
+//@{
+{
+ var done = a_test.done.bind(a_test);
+ var operationUnforgeable = member.isUnforgeable;
+ var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);
+ // "The property has attributes { [[Writable]]: B,
+ // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
+ // operation is unforgeable on the interface, and true otherwise".
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_equals(desc.writable, !operationUnforgeable,
+ "property should be writable if and only if not unforgeable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_equals(desc.configurable, !operationUnforgeable,
+ "property should be configurable if and only if not unforgeable");
+ // "The value of the property is a Function object whose
+ // behavior is as follows . . ."
+ assert_equals(typeof memberHolderObject[member.name], "function",
+ "property must be a function");
+ // "The value of the Function object’s “length” property is
+ // a Number determined as follows:
+ // ". . .
+ // "Return the length of the shortest argument list of the
+ // entries in S."
+ assert_equals(memberHolderObject[member.name].length,
+ minOverloadLength(this.members.filter(function(m) {
+ return m.type == "operation" && m.name == member.name;
+ })),
+ "property has wrong .length");
+
+ // Make some suitable arguments
+ var args = member.arguments.map(function(arg) {
+ return create_suitable_object(arg.idlType);
+ });
+
+ // "Let O be a value determined as follows:
+ // ". . .
+ // "Otherwise, throw a TypeError."
+ // This should be hit if the operation is not static, there is
+ // no [ImplicitThis] attribute, and the this value is null.
+ //
+ // TODO: We currently ignore the [ImplicitThis] case. Except we manually
+ // check for globals, since otherwise we'll invoke window.close(). And we
+ // have to skip this test for anything that on the proto chain of "self",
+ // since that does in fact have implicit-this behavior.
+ if (!member["static"]) {
+ var cb;
+ if (!this.is_global() &&
+ memberHolderObject[member.name] != self[member.name])
+ {
+ cb = awaitNCallbacks(2, done);
+ throwOrReject(a_test, member, memberHolderObject[member.name], null, args,
+ "calling operation with this = null didn't throw TypeError", cb);
+ } else {
+ cb = awaitNCallbacks(1, done);
+ }
+
+ // ". . . If O is not null and is also not a platform object
+ // that implements interface I, throw a TypeError."
+ //
+ // TODO: Test a platform object that implements some other
+ // interface. (Have to be sure to get inheritance right.)
+ throwOrReject(a_test, member, memberHolderObject[member.name], {}, args,
+ "calling operation with this = {} didn't throw TypeError", cb);
+ } else {
+ done();
+ }
+}
+
+//@}
+IdlInterface.prototype.test_member_stringifier = function(member)
+//@{
+{
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // ". . . the property exists on the interface prototype object."
+ var interfacePrototypeObject = self[this.name].prototype;
+ assert_own_property(self[this.name].prototype, "toString",
+ "interface prototype object missing non-static operation");
+
+ var stringifierUnforgeable = member.isUnforgeable;
+ var desc = Object.getOwnPropertyDescriptor(interfacePrototypeObject, "toString");
+ // "The property has attributes { [[Writable]]: B,
+ // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
+ // stringifier is unforgeable on the interface, and true otherwise."
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_equals(desc.writable, !stringifierUnforgeable,
+ "property should be writable if and only if not unforgeable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_equals(desc.configurable, !stringifierUnforgeable,
+ "property should be configurable if and only if not unforgeable");
+ // "The value of the property is a Function object, which behaves as
+ // follows . . ."
+ assert_equals(typeof interfacePrototypeObject.toString, "function",
+ "property must be a function");
+ // "The value of the Function object’s “length” property is the Number
+ // value 0."
+ assert_equals(interfacePrototypeObject.toString.length, 0,
+ "property has wrong .length");
+
+ // "Let O be the result of calling ToObject on the this value."
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype.toString.apply(null, []);
+ }, "calling stringifier with this = null didn't throw TypeError");
+
+ // "If O is not an object that implements the interface on which the
+ // stringifier was declared, then throw a TypeError."
+ //
+ // TODO: Test a platform object that implements some other
+ // interface. (Have to be sure to get inheritance right.)
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype.toString.apply({}, []);
+ }, "calling stringifier with this = {} didn't throw TypeError");
+ }.bind(this), this.name + " interface: stringifier");
+};
+
+//@}
+IdlInterface.prototype.test_members = function()
+//@{
+{
+ for (var i = 0; i < this.members.length; i++)
+ {
+ var member = this.members[i];
+ if (member.untested) {
+ continue;
+ }
+
+ switch (member.type) {
+ case "const":
+ this.test_member_const(member);
+ break;
+
+ case "attribute":
+ // For unforgeable attributes, we do the checks in
+ // test_interface_of instead.
+ if (!member.isUnforgeable)
+ {
+ this.test_member_attribute(member);
+ }
+ if (member.stringifier) {
+ this.test_member_stringifier(member);
+ }
+ break;
+
+ case "operation":
+ // TODO: Need to correctly handle multiple operations with the same
+ // identifier.
+ // For unforgeable operations, we do the checks in
+ // test_interface_of instead.
+ if (member.name) {
+ if (!member.isUnforgeable)
+ {
+ this.test_member_operation(member);
+ }
+ } else if (member.stringifier) {
+ this.test_member_stringifier(member);
+ }
+ break;
+
+ default:
+ // TODO: check more member types.
+ break;
+ }
+ }
+};
+
+//@}
+IdlInterface.prototype.test_object = function(desc)
+//@{
+{
+ var obj, exception = null;
+ try
+ {
+ obj = eval(desc);
+ }
+ catch(e)
+ {
+ exception = e;
+ }
+
+ var expected_typeof =
+ this.members.some(function(member) { return member.legacycaller; })
+ ? "function"
+ : "object";
+
+ this.test_primary_interface_of(desc, obj, exception, expected_typeof);
+ var current_interface = this;
+ while (current_interface)
+ {
+ if (!(current_interface.name in this.array.members))
+ {
+ throw "Interface " + current_interface.name + " not found (inherited by " + this.name + ")";
+ }
+ if (current_interface.prevent_multiple_testing && current_interface.already_tested)
+ {
+ return;
+ }
+ current_interface.test_interface_of(desc, obj, exception, expected_typeof);
+ current_interface = this.array.members[current_interface.base];
+ }
+};
+
+//@}
+IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)
+//@{
+{
+ // We can't easily test that its prototype is correct if there's no
+ // interface object, or the object is from a different global environment
+ // (not instanceof Object). TODO: test in this case that its prototype at
+ // least looks correct, even if we can't test that it's actually correct.
+ if (!this.has_extended_attribute("NoInterfaceObject")
+ && (typeof obj != expected_typeof || obj instanceof Object))
+ {
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // "The value of the internal [[Prototype]] property of the
+ // platform object is the interface prototype object of the primary
+ // interface from the platform object’s associated global
+ // environment."
+ assert_equals(Object.getPrototypeOf(obj),
+ self[this.name].prototype,
+ desc + "'s prototype is not " + this.name + ".prototype");
+ }.bind(this), this.name + " must be primary interface of " + desc);
+ }
+
+ // "The class string of a platform object that implements one or more
+ // interfaces must be the identifier of the primary interface of the
+ // platform object."
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ assert_class_string(obj, this.name, "class string of " + desc);
+ if (!this.has_stringifier())
+ {
+ assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")");
+ }
+ }.bind(this), "Stringification of " + desc);
+};
+
+//@}
+IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)
+//@{
+{
+ // TODO: Indexed and named properties, more checks on interface members
+ this.already_tested = true;
+
+ for (var i = 0; i < this.members.length; i++)
+ {
+ var member = this.members[i];
+ if (member.type == "attribute" && member.isUnforgeable)
+ {
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ this.do_interface_attribute_asserts(obj, member);
+ }.bind(this), this.name + " interface: " + desc + ' must have own property "' + member.name + '"');
+ }
+ else if (member.type == "operation" &&
+ member.name &&
+ member.isUnforgeable)
+ {
+ var a_test = async_test(this.name + " interface: " + desc + ' must have own property "' + member.name + '"');
+ a_test.step(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ assert_own_property(obj, member.name,
+ "Doesn't have the unforgeable operation property");
+ this.do_member_operation_asserts(obj, member, a_test);
+ }.bind(this));
+ }
+ else if ((member.type == "const"
+ || member.type == "attribute"
+ || member.type == "operation")
+ && member.name)
+ {
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ if (!member["static"]) {
+ if (!this.is_global()) {
+ assert_inherits(obj, member.name);
+ } else {
+ assert_own_property(obj, member.name);
+ }
+
+ if (member.type == "const")
+ {
+ assert_equals(obj[member.name], constValue(member.value));
+ }
+ if (member.type == "attribute")
+ {
+ // Attributes are accessor properties, so they might
+ // legitimately throw an exception rather than returning
+ // anything.
+ var property, thrown = false;
+ try
+ {
+ property = obj[member.name];
+ }
+ catch (e)
+ {
+ thrown = true;
+ }
+ if (!thrown)
+ {
+ this.array.assert_type_is(property, member.idlType);
+ }
+ }
+ if (member.type == "operation")
+ {
+ assert_equals(typeof obj[member.name], "function");
+ }
+ }
+ }.bind(this), this.name + " interface: " + desc + ' must inherit property "' + member.name + '" with the proper type (' + i + ')');
+ }
+ // TODO: This is wrong if there are multiple operations with the same
+ // identifier.
+ // TODO: Test passing arguments of the wrong type.
+ if (member.type == "operation" && member.name && member.arguments.length)
+ {
+ var a_test = async_test( this.name + " interface: calling " + member.name +
+ "(" + member.arguments.map(function(m) { return m.idlType.idlType; }) +
+ ") on " + desc + " with too few arguments must throw TypeError");
+ a_test.step(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ if (!member["static"]) {
+ if (!this.is_global() && !member.isUnforgeable) {
+ assert_inherits(obj, member.name);
+ } else {
+ assert_own_property(obj, member.name);
+ }
+ }
+ else
+ {
+ assert_false(member.name in obj);
+ }
+
+ var minLength = minOverloadLength(this.members.filter(function(m) {
+ return m.type == "operation" && m.name == member.name;
+ }));
+ var args = [];
+ var cb = awaitNCallbacks(minLength, a_test.done.bind(a_test));
+ for (var i = 0; i < minLength; i++) {
+ throwOrReject(a_test, member, obj[member.name], obj, args, "Called with " + i + " arguments", cb);
+
+ args.push(create_suitable_object(member.arguments[i].idlType));
+ }
+ if (minLength === 0) {
+ cb();
+ }
+ }.bind(this));
+ }
+ }
+};
+
+//@}
+IdlInterface.prototype.has_stringifier = function()
+//@{
+{
+ if (this.members.some(function(member) { return member.stringifier; })) {
+ return true;
+ }
+ if (this.base &&
+ this.array.members[this.base].has_stringifier()) {
+ return true;
+ }
+ return false;
+};
+
+//@}
+IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member)
+//@{
+{
+ // This function tests WebIDL as of 2015-01-27.
+ // TODO: Consider [Exposed].
+
+ // This is called by test_member_attribute() with the prototype as obj if
+ // it is not a global, and the global otherwise, and by test_interface_of()
+ // with the object as obj.
+
+ // "For each exposed attribute of the interface, whether it was declared on
+ // the interface itself or one of its consequential interfaces, there MUST
+ // exist a corresponding property. The characteristics of this property are
+ // as follows:"
+
+ // "The name of the property is the identifier of the attribute."
+ assert_own_property(obj, member.name);
+
+ // "The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where:
+ // "configurable is false if the attribute was declared with the
+ // [Unforgeable] extended attribute and true otherwise;
+ // "G is the attribute getter, defined below; and
+ // "S is the attribute setter, also defined below."
+ var desc = Object.getOwnPropertyDescriptor(obj, member.name);
+ assert_false("value" in desc, 'property descriptor has value but is supposed to be accessor');
+ assert_false("writable" in desc, 'property descriptor has "writable" field but is supposed to be accessor');
+ assert_true(desc.enumerable, "property is not enumerable");
+ if (member.isUnforgeable)
+ {
+ assert_false(desc.configurable, "[Unforgeable] property must not be configurable");
+ }
+ else
+ {
+ assert_true(desc.configurable, "property must be configurable");
+ }
+
+
+ // "The attribute getter is a Function object whose behavior when invoked
+ // is as follows:"
+ assert_equals(typeof desc.get, "function", "getter must be Function");
+
+ // "If the attribute is a regular attribute, then:"
+ if (!member["static"]) {
+ // "If O is not a platform object that implements I, then:
+ // "If the attribute was specified with the [LenientThis] extended
+ // attribute, then return undefined.
+ // "Otherwise, throw a TypeError."
+ if (!member.has_extended_attribute("LenientThis")) {
+ assert_throws(new TypeError(), function() {
+ desc.get.call({});
+ }.bind(this), "calling getter on wrong object type must throw TypeError");
+ } else {
+ assert_equals(desc.get.call({}), undefined,
+ "calling getter on wrong object type must return undefined");
+ }
+ }
+
+ // "The value of the Function object’s “length” property is the Number
+ // value 0."
+ assert_equals(desc.get.length, 0, "getter length must be 0");
+
+
+ // TODO: Test calling setter on the interface prototype (should throw
+ // TypeError in most cases).
+ if (member.readonly
+ && !member.has_extended_attribute("PutForwards")
+ && !member.has_extended_attribute("Replaceable"))
+ {
+ // "The attribute setter is undefined if the attribute is declared
+ // readonly and has neither a [PutForwards] nor a [Replaceable]
+ // extended attribute declared on it."
+ assert_equals(desc.set, undefined, "setter must be undefined for readonly attributes");
+ }
+ else
+ {
+ // "Otherwise, it is a Function object whose behavior when
+ // invoked is as follows:"
+ assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes");
+
+ // "If the attribute is a regular attribute, then:"
+ if (!member["static"]) {
+ // "If /validThis/ is false and the attribute was not specified
+ // with the [LenientThis] extended attribute, then throw a
+ // TypeError."
+ // "If the attribute is declared with a [Replaceable] extended
+ // attribute, then: ..."
+ // "If validThis is false, then return."
+ if (!member.has_extended_attribute("LenientThis")) {
+ assert_throws(new TypeError(), function() {
+ desc.set.call({});
+ }.bind(this), "calling setter on wrong object type must throw TypeError");
+ } else {
+ assert_equals(desc.set.call({}), undefined,
+ "calling setter on wrong object type must return undefined");
+ }
+ }
+
+ // "The value of the Function object’s “length” property is the Number
+ // value 1."
+ assert_equals(desc.set.length, 1, "setter length must be 1");
+ }
+}
+//@}
+
+/// IdlInterfaceMember ///
+function IdlInterfaceMember(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "ifMember" production.
+ * We just forward all properties to this object without modification,
+ * except for special extAttrs handling.
+ */
+ for (var k in obj)
+ {
+ this[k] = obj[k];
+ }
+ if (!("extAttrs" in this))
+ {
+ this.extAttrs = [];
+ }
+
+ this.isUnforgeable = this.has_extended_attribute("Unforgeable");
+}
+
+//@}
+IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);
+
+/// Internal helper functions ///
+function create_suitable_object(type)
+//@{
+{
+ /**
+ * type is an object produced by the WebIDLParser.js "type" production. We
+ * return a JavaScript value that matches the type, if we can figure out
+ * how.
+ */
+ if (type.nullable)
+ {
+ return null;
+ }
+ switch (type.idlType)
+ {
+ case "any":
+ case "boolean":
+ return true;
+
+ case "byte": case "octet": case "short": case "unsigned short":
+ case "long": case "unsigned long": case "long long":
+ case "unsigned long long": case "float": case "double":
+ case "unrestricted float": case "unrestricted double":
+ return 7;
+
+ case "DOMString":
+ case "ByteString":
+ case "USVString":
+ return "foo";
+
+ case "object":
+ return {a: "b"};
+
+ case "Node":
+ return document.createTextNode("abc");
+ }
+ return null;
+}
+//@}
+
+/// IdlEnum ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlEnum(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "dictionary"
+ * production.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** An array of values produced by the "enum" production. */
+ this.values = obj.values;
+
+}
+//@}
+
+IdlEnum.prototype = Object.create(IdlObject.prototype);
+
+/// IdlTypedef ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlTypedef(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "typedef"
+ * production.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** An array of values produced by the "typedef" production. */
+ this.values = obj.values;
+
+}
+//@}
+
+IdlTypedef.prototype = Object.create(IdlObject.prototype);
+
+}());
+// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
diff --git a/testing/web-platform/tests/resources/readme.md b/testing/web-platform/tests/resources/readme.md
new file mode 100644
index 000000000..eed909064
--- /dev/null
+++ b/testing/web-platform/tests/resources/readme.md
@@ -0,0 +1,23 @@
+## Introduction ##
+
+testharness.js provides a framework for writing low-level tests of
+browser functionality in javascript. It provides a convenient API for
+making assertions and is intended to work for both simple synchronous
+tests and for tests of asynchronous behaviour.
+
+## Getting Started ##
+
+To use testharness.js you must include two scripts, in the order given:
+
+``` html
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+```
+
+## Full documentation ##
+
+Full user documentation for the API is in the
+[docs/api.md](https://github.com/w3c/testharness.js/blob/master/docs/api.md) file.
+
+You can also read a tutorial on
+[Using testharness.js](http://darobin.github.com/test-harness-tutorial/docs/using-testharness.html).
diff --git a/testing/web-platform/tests/resources/testharness.css b/testing/web-platform/tests/resources/testharness.css
new file mode 100644
index 000000000..e2ed5a043
--- /dev/null
+++ b/testing/web-platform/tests/resources/testharness.css
@@ -0,0 +1,102 @@
+html {
+ font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans;
+}
+
+#log .warning,
+#log .warning a {
+ color: black;
+ background: yellow;
+}
+
+#log .error,
+#log .error a {
+ color: white;
+ background: red;
+}
+
+section#summary {
+ margin-bottom:1em;
+}
+
+table#results {
+ border-collapse:collapse;
+ table-layout:fixed;
+ width:100%;
+}
+
+table#results th:first-child,
+table#results td:first-child {
+ width:4em;
+}
+
+table#results th:last-child,
+table#results td:last-child {
+ width:50%;
+}
+
+table#results.assertions th:last-child,
+table#results.assertions td:last-child {
+ width:35%;
+}
+
+table#results th {
+ padding:0;
+ padding-bottom:0.5em;
+ border-bottom:medium solid black;
+}
+
+table#results td {
+ padding:1em;
+ padding-bottom:0.5em;
+ border-bottom:thin solid black;
+}
+
+tr.pass > td:first-child {
+ color:green;
+}
+
+tr.fail > td:first-child {
+ color:red;
+}
+
+tr.timeout > td:first-child {
+ color:red;
+}
+
+tr.notrun > td:first-child {
+ color:blue;
+}
+
+.pass > td:first-child, .fail > td:first-child, .timeout > td:first-child, .notrun > td:first-child {
+ font-variant:small-caps;
+}
+
+table#results span {
+ display:block;
+}
+
+table#results span.expected {
+ font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+ white-space:pre;
+}
+
+table#results span.actual {
+ font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+ white-space:pre;
+}
+
+span.ok {
+ color:green;
+}
+
+tr.error {
+ color:red;
+}
+
+span.timeout {
+ color:red;
+}
+
+span.ok, span.timeout, span.error {
+ font-variant:small-caps;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/testharness.js b/testing/web-platform/tests/resources/testharness.js
new file mode 100644
index 000000000..5b924b109
--- /dev/null
+++ b/testing/web-platform/tests/resources/testharness.js
@@ -0,0 +1,2682 @@
+/*global self*/
+/*jshint latedef: nofunc*/
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+/* Documentation is in docs/api.md */
+
+(function ()
+{
+ var debug = false;
+ // default timeout is 10 seconds, test can override if needed
+ var settings = {
+ output:true,
+ harness_timeout:{
+ "normal":10000,
+ "long":60000
+ },
+ test_timeout:null,
+ message_events: ["start", "test_state", "result", "completion"]
+ };
+
+ var xhtml_ns = "http://www.w3.org/1999/xhtml";
+
+ /*
+ * TestEnvironment is an abstraction for the environment in which the test
+ * harness is used. Each implementation of a test environment has to provide
+ * the following interface:
+ *
+ * interface TestEnvironment {
+ * // Invoked after the global 'tests' object has been created and it's
+ * // safe to call add_*_callback() to register event handlers.
+ * void on_tests_ready();
+ *
+ * // Invoked after setup() has been called to notify the test environment
+ * // of changes to the test harness properties.
+ * void on_new_harness_properties(object properties);
+ *
+ * // Should return a new unique default test name.
+ * DOMString next_default_test_name();
+ *
+ * // Should return the test harness timeout duration in milliseconds.
+ * float test_timeout();
+ *
+ * // Should return the global scope object.
+ * object global_scope();
+ * };
+ */
+
+ /*
+ * A test environment with a DOM. The global object is 'window'. By default
+ * test results are displayed in a table. Any parent windows receive
+ * callbacks or messages via postMessage() when test events occur. See
+ * apisample11.html and apisample12.html.
+ */
+ function WindowTestEnvironment() {
+ this.name_counter = 0;
+ this.window_cache = null;
+ this.output_handler = null;
+ this.all_loaded = false;
+ var this_obj = this;
+ this.message_events = [];
+
+ this.message_functions = {
+ start: [add_start_callback, remove_start_callback,
+ function (properties) {
+ this_obj._dispatch("start_callback", [properties],
+ {type: "start", properties: properties});
+ }],
+
+ test_state: [add_test_state_callback, remove_test_state_callback,
+ function(test) {
+ this_obj._dispatch("test_state_callback", [test],
+ {type: "test_state",
+ test: test.structured_clone()});
+ }],
+ result: [add_result_callback, remove_result_callback,
+ function (test) {
+ this_obj.output_handler.show_status();
+ this_obj._dispatch("result_callback", [test],
+ {type: "result",
+ test: test.structured_clone()});
+ }],
+ completion: [add_completion_callback, remove_completion_callback,
+ function (tests, harness_status) {
+ var cloned_tests = map(tests, function(test) {
+ return test.structured_clone();
+ });
+ this_obj._dispatch("completion_callback", [tests, harness_status],
+ {type: "complete",
+ tests: cloned_tests,
+ status: harness_status.structured_clone()});
+ }]
+ }
+
+ on_event(window, 'load', function() {
+ this_obj.all_loaded = true;
+ });
+ }
+
+ WindowTestEnvironment.prototype._dispatch = function(selector, callback_args, message_arg) {
+ this._forEach_windows(
+ function(w, same_origin) {
+ if (same_origin) {
+ try {
+ var has_selector = selector in w;
+ } catch(e) {
+ // If document.domain was set at some point same_origin can be
+ // wrong and the above will fail.
+ has_selector = false;
+ }
+ if (has_selector) {
+ try {
+ w[selector].apply(undefined, callback_args);
+ } catch (e) {
+ if (debug) {
+ throw e;
+ }
+ }
+ }
+ }
+ if (supports_post_message(w) && w !== self) {
+ w.postMessage(message_arg, "*");
+ }
+ });
+ };
+
+ WindowTestEnvironment.prototype._forEach_windows = function(callback) {
+ // Iterate of the the windows [self ... top, opener]. The callback is passed
+ // two objects, the first one is the windows object itself, the second one
+ // is a boolean indicating whether or not its on the same origin as the
+ // current window.
+ var cache = this.window_cache;
+ if (!cache) {
+ cache = [[self, true]];
+ var w = self;
+ var i = 0;
+ var so;
+ var origins = location.ancestorOrigins;
+ while (w != w.parent) {
+ w = w.parent;
+ // In WebKit, calls to parent windows' properties that aren't on the same
+ // origin cause an error message to be displayed in the error console but
+ // don't throw an exception. This is a deviation from the current HTML5
+ // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504
+ // The problem with WebKit's behavior is that it pollutes the error console
+ // with error messages that can't be caught.
+ //
+ // This issue can be mitigated by relying on the (for now) proprietary
+ // `location.ancestorOrigins` property which returns an ordered list of
+ // the origins of enclosing windows. See:
+ // http://trac.webkit.org/changeset/113945.
+ if (origins) {
+ so = (location.origin == origins[i]);
+ } else {
+ so = is_same_origin(w);
+ }
+ cache.push([w, so]);
+ i++;
+ }
+ w = window.opener;
+ if (w) {
+ // window.opener isn't included in the `location.ancestorOrigins` prop.
+ // We'll just have to deal with a simple check and an error msg on WebKit
+ // browsers in this case.
+ cache.push([w, is_same_origin(w)]);
+ }
+ this.window_cache = cache;
+ }
+
+ forEach(cache,
+ function(a) {
+ callback.apply(null, a);
+ });
+ };
+
+ WindowTestEnvironment.prototype.on_tests_ready = function() {
+ var output = new Output();
+ this.output_handler = output;
+
+ var this_obj = this;
+
+ add_start_callback(function (properties) {
+ this_obj.output_handler.init(properties);
+ });
+
+ add_test_state_callback(function(test) {
+ this_obj.output_handler.show_status();
+ });
+
+ add_result_callback(function (test) {
+ this_obj.output_handler.show_status();
+ });
+
+ add_completion_callback(function (tests, harness_status) {
+ this_obj.output_handler.show_results(tests, harness_status);
+ });
+ this.setup_messages(settings.message_events);
+ };
+
+ WindowTestEnvironment.prototype.setup_messages = function(new_events) {
+ var this_obj = this;
+ forEach(settings.message_events, function(x) {
+ var current_dispatch = this_obj.message_events.indexOf(x) !== -1;
+ var new_dispatch = new_events.indexOf(x) !== -1;
+ if (!current_dispatch && new_dispatch) {
+ this_obj.message_functions[x][0](this_obj.message_functions[x][2]);
+ } else if (current_dispatch && !new_dispatch) {
+ this_obj.message_functions[x][1](this_obj.message_functions[x][2]);
+ }
+ });
+ this.message_events = new_events;
+ }
+
+ WindowTestEnvironment.prototype.next_default_test_name = function() {
+ //Don't use document.title to work around an Opera bug in XHTML documents
+ var title = document.getElementsByTagName("title")[0];
+ var prefix = (title && title.firstChild && title.firstChild.data) || "Untitled";
+ var suffix = this.name_counter > 0 ? " " + this.name_counter : "";
+ this.name_counter++;
+ return prefix + suffix;
+ };
+
+ WindowTestEnvironment.prototype.on_new_harness_properties = function(properties) {
+ this.output_handler.setup(properties);
+ if (properties.hasOwnProperty("message_events")) {
+ this.setup_messages(properties.message_events);
+ }
+ };
+
+ WindowTestEnvironment.prototype.add_on_loaded_callback = function(callback) {
+ on_event(window, 'load', callback);
+ };
+
+ WindowTestEnvironment.prototype.test_timeout = function() {
+ var metas = document.getElementsByTagName("meta");
+ for (var i = 0; i < metas.length; i++) {
+ if (metas[i].name == "timeout") {
+ if (metas[i].content == "long") {
+ return settings.harness_timeout.long;
+ }
+ break;
+ }
+ }
+ return settings.harness_timeout.normal;
+ };
+
+ WindowTestEnvironment.prototype.global_scope = function() {
+ return window;
+ };
+
+ /*
+ * Base TestEnvironment implementation for a generic web worker.
+ *
+ * Workers accumulate test results. One or more clients can connect and
+ * retrieve results from a worker at any time.
+ *
+ * WorkerTestEnvironment supports communicating with a client via a
+ * MessagePort. The mechanism for determining the appropriate MessagePort
+ * for communicating with a client depends on the type of worker and is
+ * implemented by the various specializations of WorkerTestEnvironment
+ * below.
+ *
+ * A client document using testharness can use fetch_tests_from_worker() to
+ * retrieve results from a worker. See apisample16.html.
+ */
+ function WorkerTestEnvironment() {
+ this.name_counter = 0;
+ this.all_loaded = true;
+ this.message_list = [];
+ this.message_ports = [];
+ }
+
+ WorkerTestEnvironment.prototype._dispatch = function(message) {
+ this.message_list.push(message);
+ for (var i = 0; i < this.message_ports.length; ++i)
+ {
+ this.message_ports[i].postMessage(message);
+ }
+ };
+
+ // The only requirement is that port has a postMessage() method. It doesn't
+ // have to be an instance of a MessagePort, and often isn't.
+ WorkerTestEnvironment.prototype._add_message_port = function(port) {
+ this.message_ports.push(port);
+ for (var i = 0; i < this.message_list.length; ++i)
+ {
+ port.postMessage(this.message_list[i]);
+ }
+ };
+
+ WorkerTestEnvironment.prototype.next_default_test_name = function() {
+ var suffix = this.name_counter > 0 ? " " + this.name_counter : "";
+ this.name_counter++;
+ return "Untitled" + suffix;
+ };
+
+ WorkerTestEnvironment.prototype.on_new_harness_properties = function() {};
+
+ WorkerTestEnvironment.prototype.on_tests_ready = function() {
+ var this_obj = this;
+ add_start_callback(
+ function(properties) {
+ this_obj._dispatch({
+ type: "start",
+ properties: properties,
+ });
+ });
+ add_test_state_callback(
+ function(test) {
+ this_obj._dispatch({
+ type: "test_state",
+ test: test.structured_clone()
+ });
+ });
+ add_result_callback(
+ function(test) {
+ this_obj._dispatch({
+ type: "result",
+ test: test.structured_clone()
+ });
+ });
+ add_completion_callback(
+ function(tests, harness_status) {
+ this_obj._dispatch({
+ type: "complete",
+ tests: map(tests,
+ function(test) {
+ return test.structured_clone();
+ }),
+ status: harness_status.structured_clone()
+ });
+ });
+ };
+
+ WorkerTestEnvironment.prototype.add_on_loaded_callback = function() {};
+
+ WorkerTestEnvironment.prototype.test_timeout = function() {
+ // Tests running in a worker don't have a default timeout. I.e. all
+ // worker tests behave as if settings.explicit_timeout is true.
+ return null;
+ };
+
+ WorkerTestEnvironment.prototype.global_scope = function() {
+ return self;
+ };
+
+ /*
+ * Dedicated web workers.
+ * https://html.spec.whatwg.org/multipage/workers.html#dedicatedworkerglobalscope
+ *
+ * This class is used as the test_environment when testharness is running
+ * inside a dedicated worker.
+ */
+ function DedicatedWorkerTestEnvironment() {
+ WorkerTestEnvironment.call(this);
+ // self is an instance of DedicatedWorkerGlobalScope which exposes
+ // a postMessage() method for communicating via the message channel
+ // established when the worker is created.
+ this._add_message_port(self);
+ }
+ DedicatedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype);
+
+ DedicatedWorkerTestEnvironment.prototype.on_tests_ready = function() {
+ WorkerTestEnvironment.prototype.on_tests_ready.call(this);
+ // In the absence of an onload notification, we a require dedicated
+ // workers to explicitly signal when the tests are done.
+ tests.wait_for_finish = true;
+ };
+
+ /*
+ * Shared web workers.
+ * https://html.spec.whatwg.org/multipage/workers.html#sharedworkerglobalscope
+ *
+ * This class is used as the test_environment when testharness is running
+ * inside a shared web worker.
+ */
+ function SharedWorkerTestEnvironment() {
+ WorkerTestEnvironment.call(this);
+ var this_obj = this;
+ // Shared workers receive message ports via the 'onconnect' event for
+ // each connection.
+ self.addEventListener("connect",
+ function(message_event) {
+ this_obj._add_message_port(message_event.source);
+ });
+ }
+ SharedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype);
+
+ SharedWorkerTestEnvironment.prototype.on_tests_ready = function() {
+ WorkerTestEnvironment.prototype.on_tests_ready.call(this);
+ // In the absence of an onload notification, we a require shared
+ // workers to explicitly signal when the tests are done.
+ tests.wait_for_finish = true;
+ };
+
+ /*
+ * Service workers.
+ * http://www.w3.org/TR/service-workers/
+ *
+ * This class is used as the test_environment when testharness is running
+ * inside a service worker.
+ */
+ function ServiceWorkerTestEnvironment() {
+ WorkerTestEnvironment.call(this);
+ this.all_loaded = false;
+ this.on_loaded_callback = null;
+ var this_obj = this;
+ self.addEventListener("message",
+ function(event) {
+ if (event.data.type && event.data.type === "connect") {
+ if (event.ports && event.ports[0]) {
+ // If a MessageChannel was passed, then use it to
+ // send results back to the main window. This
+ // allows the tests to work even if the browser
+ // does not fully support MessageEvent.source in
+ // ServiceWorkers yet.
+ this_obj._add_message_port(event.ports[0]);
+ event.ports[0].start();
+ } else {
+ // If there is no MessageChannel, then attempt to
+ // use the MessageEvent.source to send results
+ // back to the main window.
+ this_obj._add_message_port(event.source);
+ }
+ }
+ });
+
+ // The oninstall event is received after the service worker script and
+ // all imported scripts have been fetched and executed. It's the
+ // equivalent of an onload event for a document. All tests should have
+ // been added by the time this event is received, thus it's not
+ // necessary to wait until the onactivate event.
+ on_event(self, "install",
+ function(event) {
+ this_obj.all_loaded = true;
+ if (this_obj.on_loaded_callback) {
+ this_obj.on_loaded_callback();
+ }
+ });
+ }
+ ServiceWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype);
+
+ ServiceWorkerTestEnvironment.prototype.add_on_loaded_callback = function(callback) {
+ if (this.all_loaded) {
+ callback();
+ } else {
+ this.on_loaded_callback = callback;
+ }
+ };
+
+ function create_test_environment() {
+ if ('document' in self) {
+ return new WindowTestEnvironment();
+ }
+ if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ return new DedicatedWorkerTestEnvironment();
+ }
+ if ('SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ return new SharedWorkerTestEnvironment();
+ }
+ if ('ServiceWorkerGlobalScope' in self &&
+ self instanceof ServiceWorkerGlobalScope) {
+ return new ServiceWorkerTestEnvironment();
+ }
+ if ('WorkerGlobalScope' in self &&
+ self instanceof WorkerGlobalScope) {
+ return new DedicatedWorkerTestEnvironment();
+ }
+
+ throw new Error("Unsupported test environment");
+ }
+
+ var test_environment = create_test_environment();
+
+ function is_shared_worker(worker) {
+ return 'SharedWorker' in self && worker instanceof SharedWorker;
+ }
+
+ function is_service_worker(worker) {
+ return 'ServiceWorker' in self && worker instanceof ServiceWorker;
+ }
+
+ /*
+ * API functions
+ */
+
+ function test(func, name, properties)
+ {
+ var test_name = name ? name : test_environment.next_default_test_name();
+ properties = properties ? properties : {};
+ var test_obj = new Test(test_name, properties);
+ test_obj.step(func, test_obj, test_obj);
+ if (test_obj.phase === test_obj.phases.STARTED) {
+ test_obj.done();
+ }
+ }
+
+ function async_test(func, name, properties)
+ {
+ if (typeof func !== "function") {
+ properties = name;
+ name = func;
+ func = null;
+ }
+ var test_name = name ? name : test_environment.next_default_test_name();
+ properties = properties ? properties : {};
+ var test_obj = new Test(test_name, properties);
+ if (func) {
+ test_obj.step(func, test_obj, test_obj);
+ }
+ return test_obj;
+ }
+
+ function promise_test(func, name, properties) {
+ var test = async_test(name, properties);
+ // If there is no promise tests queue make one.
+ if (!tests.promise_tests) {
+ tests.promise_tests = Promise.resolve();
+ }
+ tests.promise_tests = tests.promise_tests.then(function() {
+ return Promise.resolve(test.step(func, test, test))
+ .then(
+ function() {
+ test.done();
+ })
+ .catch(test.step_func(
+ function(value) {
+ if (value instanceof AssertionError) {
+ throw value;
+ }
+ assert(false, "promise_test", null,
+ "Unhandled rejection with value: ${value}", {value:value});
+ }));
+ });
+ }
+
+ function promise_rejects(test, expected, promise, description) {
+ return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) {
+ assert_throws(expected, function() { throw e }, description);
+ });
+ }
+
+ /**
+ * This constructor helper allows DOM events to be handled using Promises,
+ * which can make it a lot easier to test a very specific series of events,
+ * including ensuring that unexpected events are not fired at any point.
+ */
+ function EventWatcher(test, watchedNode, eventTypes)
+ {
+ if (typeof eventTypes == 'string') {
+ eventTypes = [eventTypes];
+ }
+
+ var waitingFor = null;
+
+ var eventHandler = test.step_func(function(evt) {
+ assert_true(!!waitingFor,
+ 'Not expecting event, but got ' + evt.type + ' event');
+ assert_equals(evt.type, waitingFor.types[0],
+ 'Expected ' + waitingFor.types[0] + ' event, but got ' +
+ evt.type + ' event instead');
+ if (waitingFor.types.length > 1) {
+ // Pop first event from array
+ waitingFor.types.shift();
+ return;
+ }
+ // We need to null out waitingFor before calling the resolve function
+ // since the Promise's resolve handlers may call wait_for() which will
+ // need to set waitingFor.
+ var resolveFunc = waitingFor.resolve;
+ waitingFor = null;
+ resolveFunc(evt);
+ });
+
+ for (var i = 0; i < eventTypes.length; i++) {
+ watchedNode.addEventListener(eventTypes[i], eventHandler);
+ }
+
+ /**
+ * Returns a Promise that will resolve after the specified event or
+ * series of events has occured.
+ */
+ this.wait_for = function(types) {
+ if (waitingFor) {
+ return Promise.reject('Already waiting for an event or events');
+ }
+ if (typeof types == 'string') {
+ types = [types];
+ }
+ return new Promise(function(resolve, reject) {
+ waitingFor = {
+ types: types,
+ resolve: resolve,
+ reject: reject
+ };
+ });
+ };
+
+ function stop_watching() {
+ for (var i = 0; i < eventTypes.length; i++) {
+ watchedNode.removeEventListener(eventTypes[i], eventHandler);
+ }
+ };
+
+ test.add_cleanup(stop_watching);
+
+ return this;
+ }
+ expose(EventWatcher, 'EventWatcher');
+
+ function setup(func_or_properties, maybe_properties)
+ {
+ var func = null;
+ var properties = {};
+ if (arguments.length === 2) {
+ func = func_or_properties;
+ properties = maybe_properties;
+ } else if (func_or_properties instanceof Function) {
+ func = func_or_properties;
+ } else {
+ properties = func_or_properties;
+ }
+ tests.setup(func, properties);
+ test_environment.on_new_harness_properties(properties);
+ }
+
+ function done() {
+ if (tests.tests.length === 0) {
+ tests.set_file_is_test();
+ }
+ if (tests.file_is_test) {
+ tests.tests[0].done();
+ }
+ tests.end_wait();
+ }
+
+ function generate_tests(func, args, properties) {
+ forEach(args, function(x, i)
+ {
+ var name = x[0];
+ test(function()
+ {
+ func.apply(this, x.slice(1));
+ },
+ name,
+ Array.isArray(properties) ? properties[i] : properties);
+ });
+ }
+
+ function on_event(object, event, callback)
+ {
+ object.addEventListener(event, callback, false);
+ }
+
+ function step_timeout(f, t) {
+ var outer_this = this;
+ var args = Array.prototype.slice.call(arguments, 2);
+ return setTimeout(function() {
+ f.apply(outer_this, args);
+ }, t * tests.timeout_multiplier);
+ }
+
+ expose(test, 'test');
+ expose(async_test, 'async_test');
+ expose(promise_test, 'promise_test');
+ expose(promise_rejects, 'promise_rejects');
+ expose(generate_tests, 'generate_tests');
+ expose(setup, 'setup');
+ expose(done, 'done');
+ expose(on_event, 'on_event');
+ expose(step_timeout, 'step_timeout');
+
+ /*
+ * Return a string truncated to the given length, with ... added at the end
+ * if it was longer.
+ */
+ function truncate(s, len)
+ {
+ if (s.length > len) {
+ return s.substring(0, len - 3) + "...";
+ }
+ return s;
+ }
+
+ /*
+ * Return true if object is probably a Node object.
+ */
+ function is_node(object)
+ {
+ // I use duck-typing instead of instanceof, because
+ // instanceof doesn't work if the node is from another window (like an
+ // iframe's contentWindow):
+ // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295
+ try {
+ var has_node_properties = ("nodeType" in object &&
+ "nodeName" in object &&
+ "nodeValue" in object &&
+ "childNodes" in object);
+ } catch (e) {
+ // We're probably cross-origin, which means we aren't a node
+ return false;
+ }
+
+ if (has_node_properties) {
+ try {
+ object.nodeType;
+ } catch (e) {
+ // The object is probably Node.prototype or another prototype
+ // object that inherits from it, and not a Node instance.
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ var replacements = {
+ "0": "0",
+ "1": "x01",
+ "2": "x02",
+ "3": "x03",
+ "4": "x04",
+ "5": "x05",
+ "6": "x06",
+ "7": "x07",
+ "8": "b",
+ "9": "t",
+ "10": "n",
+ "11": "v",
+ "12": "f",
+ "13": "r",
+ "14": "x0e",
+ "15": "x0f",
+ "16": "x10",
+ "17": "x11",
+ "18": "x12",
+ "19": "x13",
+ "20": "x14",
+ "21": "x15",
+ "22": "x16",
+ "23": "x17",
+ "24": "x18",
+ "25": "x19",
+ "26": "x1a",
+ "27": "x1b",
+ "28": "x1c",
+ "29": "x1d",
+ "30": "x1e",
+ "31": "x1f",
+ "0xfffd": "ufffd",
+ "0xfffe": "ufffe",
+ "0xffff": "uffff",
+ };
+
+ /*
+ * Convert a value to a nice, human-readable string
+ */
+ function format_value(val, seen)
+ {
+ if (!seen) {
+ seen = [];
+ }
+ if (typeof val === "object" && val !== null) {
+ if (seen.indexOf(val) >= 0) {
+ return "[...]";
+ }
+ seen.push(val);
+ }
+ if (Array.isArray(val)) {
+ return "[" + val.map(function(x) {return format_value(x, seen);}).join(", ") + "]";
+ }
+
+ switch (typeof val) {
+ case "string":
+ val = val.replace("\\", "\\\\");
+ for (var p in replacements) {
+ var replace = "\\" + replacements[p];
+ val = val.replace(RegExp(String.fromCharCode(p), "g"), replace);
+ }
+ return '"' + val.replace(/"/g, '\\"') + '"';
+ case "boolean":
+ case "undefined":
+ return String(val);
+ case "number":
+ // In JavaScript, -0 === 0 and String(-0) == "0", so we have to
+ // special-case.
+ if (val === -0 && 1/val === -Infinity) {
+ return "-0";
+ }
+ return String(val);
+ case "object":
+ if (val === null) {
+ return "null";
+ }
+
+ // Special-case Node objects, since those come up a lot in my tests. I
+ // ignore namespaces.
+ if (is_node(val)) {
+ switch (val.nodeType) {
+ case Node.ELEMENT_NODE:
+ var ret = "<" + val.localName;
+ for (var i = 0; i < val.attributes.length; i++) {
+ ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"';
+ }
+ ret += ">" + val.innerHTML + "</" + val.localName + ">";
+ return "Element node " + truncate(ret, 60);
+ case Node.TEXT_NODE:
+ return 'Text node "' + truncate(val.data, 60) + '"';
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ return "ProcessingInstruction node with target " + format_value(truncate(val.target, 60)) + " and data " + format_value(truncate(val.data, 60));
+ case Node.COMMENT_NODE:
+ return "Comment node <!--" + truncate(val.data, 60) + "-->";
+ case Node.DOCUMENT_NODE:
+ return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+ case Node.DOCUMENT_TYPE_NODE:
+ return "DocumentType node";
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+ default:
+ return "Node object of unknown type";
+ }
+ }
+
+ /* falls through */
+ default:
+ try {
+ return typeof val + ' "' + truncate(String(val), 1000) + '"';
+ } catch(e) {
+ return ("[stringifying object threw " + String(e) +
+ " with type " + String(typeof e) + "]");
+ }
+ }
+ }
+ expose(format_value, "format_value");
+
+ /*
+ * Assertions
+ */
+
+ function assert_true(actual, description)
+ {
+ assert(actual === true, "assert_true", description,
+ "expected true got ${actual}", {actual:actual});
+ }
+ expose(assert_true, "assert_true");
+
+ function assert_false(actual, description)
+ {
+ assert(actual === false, "assert_false", description,
+ "expected false got ${actual}", {actual:actual});
+ }
+ expose(assert_false, "assert_false");
+
+ function same_value(x, y) {
+ if (y !== y) {
+ //NaN case
+ return x !== x;
+ }
+ if (x === 0 && y === 0) {
+ //Distinguish +0 and -0
+ return 1/x === 1/y;
+ }
+ return x === y;
+ }
+
+ function assert_equals(actual, expected, description)
+ {
+ /*
+ * Test if two primitives are equal or two objects
+ * are the same object
+ */
+ if (typeof actual != typeof expected) {
+ assert(false, "assert_equals", description,
+ "expected (" + typeof expected + ") ${expected} but got (" + typeof actual + ") ${actual}",
+ {expected:expected, actual:actual});
+ return;
+ }
+ assert(same_value(actual, expected), "assert_equals", description,
+ "expected ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_equals, "assert_equals");
+
+ function assert_not_equals(actual, expected, description)
+ {
+ /*
+ * Test if two primitives are unequal or two objects
+ * are different objects
+ */
+ assert(!same_value(actual, expected), "assert_not_equals", description,
+ "got disallowed value ${actual}",
+ {actual:actual});
+ }
+ expose(assert_not_equals, "assert_not_equals");
+
+ function assert_in_array(actual, expected, description)
+ {
+ assert(expected.indexOf(actual) != -1, "assert_in_array", description,
+ "value ${actual} not in array ${expected}",
+ {actual:actual, expected:expected});
+ }
+ expose(assert_in_array, "assert_in_array");
+
+ function assert_object_equals(actual, expected, description)
+ {
+ //This needs to be improved a great deal
+ function check_equal(actual, expected, stack)
+ {
+ stack.push(actual);
+
+ var p;
+ for (p in actual) {
+ assert(expected.hasOwnProperty(p), "assert_object_equals", description,
+ "unexpected property ${p}", {p:p});
+
+ if (typeof actual[p] === "object" && actual[p] !== null) {
+ if (stack.indexOf(actual[p]) === -1) {
+ check_equal(actual[p], expected[p], stack);
+ }
+ } else {
+ assert(same_value(actual[p], expected[p]), "assert_object_equals", description,
+ "property ${p} expected ${expected} got ${actual}",
+ {p:p, expected:expected, actual:actual});
+ }
+ }
+ for (p in expected) {
+ assert(actual.hasOwnProperty(p),
+ "assert_object_equals", description,
+ "expected property ${p} missing", {p:p});
+ }
+ stack.pop();
+ }
+ check_equal(actual, expected, []);
+ }
+ expose(assert_object_equals, "assert_object_equals");
+
+ function assert_array_equals(actual, expected, description)
+ {
+ assert(actual.length === expected.length,
+ "assert_array_equals", description,
+ "lengths differ, expected ${expected} got ${actual}",
+ {expected:expected.length, actual:actual.length});
+
+ for (var i = 0; i < actual.length; i++) {
+ assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i),
+ "assert_array_equals", description,
+ "property ${i}, property expected to be ${expected} but was ${actual}",
+ {i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing",
+ actual:actual.hasOwnProperty(i) ? "present" : "missing"});
+ assert(same_value(expected[i], actual[i]),
+ "assert_array_equals", description,
+ "property ${i}, expected ${expected} but got ${actual}",
+ {i:i, expected:expected[i], actual:actual[i]});
+ }
+ }
+ expose(assert_array_equals, "assert_array_equals");
+
+ function assert_approx_equals(actual, expected, epsilon, description)
+ {
+ /*
+ * Test if two primitive numbers are equal withing +/- epsilon
+ */
+ assert(typeof actual === "number",
+ "assert_approx_equals", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(Math.abs(actual - expected) <= epsilon,
+ "assert_approx_equals", description,
+ "expected ${expected} +/- ${epsilon} but got ${actual}",
+ {expected:expected, actual:actual, epsilon:epsilon});
+ }
+ expose(assert_approx_equals, "assert_approx_equals");
+
+ function assert_less_than(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is less than another
+ */
+ assert(typeof actual === "number",
+ "assert_less_than", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual < expected,
+ "assert_less_than", description,
+ "expected a number less than ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_less_than, "assert_less_than");
+
+ function assert_greater_than(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is greater than another
+ */
+ assert(typeof actual === "number",
+ "assert_greater_than", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual > expected,
+ "assert_greater_than", description,
+ "expected a number greater than ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_greater_than, "assert_greater_than");
+
+ function assert_between_exclusive(actual, lower, upper, description)
+ {
+ /*
+ * Test if a primitive number is between two others
+ */
+ assert(typeof actual === "number",
+ "assert_between_exclusive", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual > lower && actual < upper,
+ "assert_between_exclusive", description,
+ "expected a number greater than ${lower} " +
+ "and less than ${upper} but got ${actual}",
+ {lower:lower, upper:upper, actual:actual});
+ }
+ expose(assert_between_exclusive, "assert_between_exclusive");
+
+ function assert_less_than_equal(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is less than or equal to another
+ */
+ assert(typeof actual === "number",
+ "assert_less_than_equal", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual <= expected,
+ "assert_less_than_equal", description,
+ "expected a number less than or equal to ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_less_than_equal, "assert_less_than_equal");
+
+ function assert_greater_than_equal(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is greater than or equal to another
+ */
+ assert(typeof actual === "number",
+ "assert_greater_than_equal", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual >= expected,
+ "assert_greater_than_equal", description,
+ "expected a number greater than or equal to ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_greater_than_equal, "assert_greater_than_equal");
+
+ function assert_between_inclusive(actual, lower, upper, description)
+ {
+ /*
+ * Test if a primitive number is between to two others or equal to either of them
+ */
+ assert(typeof actual === "number",
+ "assert_between_inclusive", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual >= lower && actual <= upper,
+ "assert_between_inclusive", description,
+ "expected a number greater than or equal to ${lower} " +
+ "and less than or equal to ${upper} but got ${actual}",
+ {lower:lower, upper:upper, actual:actual});
+ }
+ expose(assert_between_inclusive, "assert_between_inclusive");
+
+ function assert_regexp_match(actual, expected, description) {
+ /*
+ * Test if a string (actual) matches a regexp (expected)
+ */
+ assert(expected.test(actual),
+ "assert_regexp_match", description,
+ "expected ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_regexp_match, "assert_regexp_match");
+
+ function assert_class_string(object, class_string, description) {
+ assert_equals({}.toString.call(object), "[object " + class_string + "]",
+ description);
+ }
+ expose(assert_class_string, "assert_class_string");
+
+
+ function _assert_own_property(name) {
+ return function(object, property_name, description)
+ {
+ assert(object.hasOwnProperty(property_name),
+ name, description,
+ "expected property ${p} missing", {p:property_name});
+ };
+ }
+ expose(_assert_own_property("assert_exists"), "assert_exists");
+ expose(_assert_own_property("assert_own_property"), "assert_own_property");
+
+ function assert_not_exists(object, property_name, description)
+ {
+ assert(!object.hasOwnProperty(property_name),
+ "assert_not_exists", description,
+ "unexpected property ${p} found", {p:property_name});
+ }
+ expose(assert_not_exists, "assert_not_exists");
+
+ function _assert_inherits(name) {
+ return function (object, property_name, description)
+ {
+ assert(typeof object === "object" || typeof object === "function",
+ name, description,
+ "provided value is not an object");
+
+ assert("hasOwnProperty" in object,
+ name, description,
+ "provided value is an object but has no hasOwnProperty method");
+
+ assert(!object.hasOwnProperty(property_name),
+ name, description,
+ "property ${p} found on object expected in prototype chain",
+ {p:property_name});
+
+ assert(property_name in object,
+ name, description,
+ "property ${p} not found in prototype chain",
+ {p:property_name});
+ };
+ }
+ expose(_assert_inherits("assert_inherits"), "assert_inherits");
+ expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute");
+
+ function assert_readonly(object, property_name, description)
+ {
+ var initial_value = object[property_name];
+ try {
+ //Note that this can have side effects in the case where
+ //the property has PutForwards
+ object[property_name] = initial_value + "a"; //XXX use some other value here?
+ assert(same_value(object[property_name], initial_value),
+ "assert_readonly", description,
+ "changing property ${p} succeeded",
+ {p:property_name});
+ } finally {
+ object[property_name] = initial_value;
+ }
+ }
+ expose(assert_readonly, "assert_readonly");
+
+ function assert_throws(code, func, description)
+ {
+ try {
+ func.call(this);
+ assert(false, "assert_throws", description,
+ "${func} did not throw", {func:func});
+ } catch (e) {
+ if (e instanceof AssertionError) {
+ throw e;
+ }
+ if (code === null) {
+ return;
+ }
+ if (typeof code === "object") {
+ assert(typeof e == "object" && "name" in e && e.name == code.name,
+ "assert_throws", description,
+ "${func} threw ${actual} (${actual_name}) expected ${expected} (${expected_name})",
+ {func:func, actual:e, actual_name:e.name,
+ expected:code,
+ expected_name:code.name});
+ return;
+ }
+
+ var code_name_map = {
+ INDEX_SIZE_ERR: 'IndexSizeError',
+ HIERARCHY_REQUEST_ERR: 'HierarchyRequestError',
+ WRONG_DOCUMENT_ERR: 'WrongDocumentError',
+ INVALID_CHARACTER_ERR: 'InvalidCharacterError',
+ NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError',
+ NOT_FOUND_ERR: 'NotFoundError',
+ NOT_SUPPORTED_ERR: 'NotSupportedError',
+ INUSE_ATTRIBUTE_ERR: 'InUseAttributeError',
+ INVALID_STATE_ERR: 'InvalidStateError',
+ SYNTAX_ERR: 'SyntaxError',
+ INVALID_MODIFICATION_ERR: 'InvalidModificationError',
+ NAMESPACE_ERR: 'NamespaceError',
+ INVALID_ACCESS_ERR: 'InvalidAccessError',
+ TYPE_MISMATCH_ERR: 'TypeMismatchError',
+ SECURITY_ERR: 'SecurityError',
+ NETWORK_ERR: 'NetworkError',
+ ABORT_ERR: 'AbortError',
+ URL_MISMATCH_ERR: 'URLMismatchError',
+ QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
+ TIMEOUT_ERR: 'TimeoutError',
+ INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError',
+ DATA_CLONE_ERR: 'DataCloneError'
+ };
+
+ var name = code in code_name_map ? code_name_map[code] : code;
+
+ var name_code_map = {
+ IndexSizeError: 1,
+ HierarchyRequestError: 3,
+ WrongDocumentError: 4,
+ InvalidCharacterError: 5,
+ NoModificationAllowedError: 7,
+ NotFoundError: 8,
+ NotSupportedError: 9,
+ InUseAttributeError: 10,
+ InvalidStateError: 11,
+ SyntaxError: 12,
+ InvalidModificationError: 13,
+ NamespaceError: 14,
+ InvalidAccessError: 15,
+ TypeMismatchError: 17,
+ SecurityError: 18,
+ NetworkError: 19,
+ AbortError: 20,
+ URLMismatchError: 21,
+ QuotaExceededError: 22,
+ TimeoutError: 23,
+ InvalidNodeTypeError: 24,
+ DataCloneError: 25,
+
+ EncodingError: 0,
+ NotReadableError: 0,
+ UnknownError: 0,
+ ConstraintError: 0,
+ DataError: 0,
+ TransactionInactiveError: 0,
+ ReadOnlyError: 0,
+ VersionError: 0,
+ OperationError: 0,
+ };
+
+ if (!(name in name_code_map)) {
+ throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()');
+ }
+
+ var required_props = { code: name_code_map[name] };
+
+ if (required_props.code === 0 ||
+ (typeof e == "object" &&
+ "name" in e &&
+ e.name !== e.name.toUpperCase() &&
+ e.name !== "DOMException")) {
+ // New style exception: also test the name property.
+ required_props.name = name;
+ }
+
+ //We'd like to test that e instanceof the appropriate interface,
+ //but we can't, because we don't know what window it was created
+ //in. It might be an instanceof the appropriate interface on some
+ //unknown other window. TODO: Work around this somehow?
+
+ assert(typeof e == "object",
+ "assert_throws", description,
+ "${func} threw ${e} with type ${type}, not an object",
+ {func:func, e:e, type:typeof e});
+
+ for (var prop in required_props) {
+ assert(typeof e == "object" && prop in e && e[prop] == required_props[prop],
+ "assert_throws", description,
+ "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}",
+ {func:func, e:e, prop:prop, actual:e[prop], expected:required_props[prop]});
+ }
+ }
+ }
+ expose(assert_throws, "assert_throws");
+
+ function assert_unreached(description) {
+ assert(false, "assert_unreached", description,
+ "Reached unreachable code");
+ }
+ expose(assert_unreached, "assert_unreached");
+
+ function assert_any(assert_func, actual, expected_array)
+ {
+ var args = [].slice.call(arguments, 3);
+ var errors = [];
+ var passed = false;
+ forEach(expected_array,
+ function(expected)
+ {
+ try {
+ assert_func.apply(this, [actual, expected].concat(args));
+ passed = true;
+ } catch (e) {
+ errors.push(e.message);
+ }
+ });
+ if (!passed) {
+ throw new AssertionError(errors.join("\n\n"));
+ }
+ }
+ expose(assert_any, "assert_any");
+
+ function Test(name, properties)
+ {
+ if (tests.file_is_test && tests.tests.length) {
+ throw new Error("Tried to create a test with file_is_test");
+ }
+ this.name = name;
+
+ this.phase = this.phases.INITIAL;
+
+ this.status = this.NOTRUN;
+ this.timeout_id = null;
+ this.index = null;
+
+ this.properties = properties;
+ var timeout = properties.timeout ? properties.timeout : settings.test_timeout;
+ if (timeout !== null) {
+ this.timeout_length = timeout * tests.timeout_multiplier;
+ } else {
+ this.timeout_length = null;
+ }
+
+ this.message = null;
+ this.stack = null;
+
+ this.steps = [];
+
+ this.cleanup_callbacks = [];
+
+ tests.push(this);
+ }
+
+ Test.statuses = {
+ PASS:0,
+ FAIL:1,
+ TIMEOUT:2,
+ NOTRUN:3
+ };
+
+ Test.prototype = merge({}, Test.statuses);
+
+ Test.prototype.phases = {
+ INITIAL:0,
+ STARTED:1,
+ HAS_RESULT:2,
+ COMPLETE:3
+ };
+
+ Test.prototype.structured_clone = function()
+ {
+ if (!this._structured_clone) {
+ var msg = this.message;
+ msg = msg ? String(msg) : msg;
+ this._structured_clone = merge({
+ name:String(this.name),
+ properties:merge({}, this.properties),
+ }, Test.statuses);
+ }
+ this._structured_clone.status = this.status;
+ this._structured_clone.message = this.message;
+ this._structured_clone.stack = this.stack;
+ this._structured_clone.index = this.index;
+ return this._structured_clone;
+ };
+
+ Test.prototype.step = function(func, this_obj)
+ {
+ if (this.phase > this.phases.STARTED) {
+ return;
+ }
+ this.phase = this.phases.STARTED;
+ //If we don't get a result before the harness times out that will be a test timout
+ this.set_status(this.TIMEOUT, "Test timed out");
+
+ tests.started = true;
+ tests.notify_test_state(this);
+
+ if (this.timeout_id === null) {
+ this.set_timeout();
+ }
+
+ this.steps.push(func);
+
+ if (arguments.length === 1) {
+ this_obj = this;
+ }
+
+ try {
+ return func.apply(this_obj, Array.prototype.slice.call(arguments, 2));
+ } catch (e) {
+ if (this.phase >= this.phases.HAS_RESULT) {
+ return;
+ }
+ var message = String((typeof e === "object" && e !== null) ? e.message : e);
+ var stack = e.stack ? e.stack : null;
+
+ this.set_status(this.FAIL, message, stack);
+ this.phase = this.phases.HAS_RESULT;
+ this.done();
+ }
+ };
+
+ Test.prototype.step_func = function(func, this_obj)
+ {
+ var test_this = this;
+
+ if (arguments.length === 1) {
+ this_obj = test_this;
+ }
+
+ return function()
+ {
+ return test_this.step.apply(test_this, [func, this_obj].concat(
+ Array.prototype.slice.call(arguments)));
+ };
+ };
+
+ Test.prototype.step_func_done = function(func, this_obj)
+ {
+ var test_this = this;
+
+ if (arguments.length === 1) {
+ this_obj = test_this;
+ }
+
+ return function()
+ {
+ if (func) {
+ test_this.step.apply(test_this, [func, this_obj].concat(
+ Array.prototype.slice.call(arguments)));
+ }
+ test_this.done();
+ };
+ };
+
+ Test.prototype.unreached_func = function(description)
+ {
+ return this.step_func(function() {
+ assert_unreached(description);
+ });
+ };
+
+ Test.prototype.step_timeout = function(f, timeout) {
+ var test_this = this;
+ var args = Array.prototype.slice.call(arguments, 2);
+ return setTimeout(this.step_func(function() {
+ return f.apply(test_this, args);
+ }), timeout * tests.timeout_multiplier);
+ }
+
+ Test.prototype.add_cleanup = function(callback) {
+ this.cleanup_callbacks.push(callback);
+ };
+
+ Test.prototype.force_timeout = function() {
+ this.set_status(this.TIMEOUT);
+ this.phase = this.phases.HAS_RESULT;
+ };
+
+ Test.prototype.set_timeout = function()
+ {
+ if (this.timeout_length !== null) {
+ var this_obj = this;
+ this.timeout_id = setTimeout(function()
+ {
+ this_obj.timeout();
+ }, this.timeout_length);
+ }
+ };
+
+ Test.prototype.set_status = function(status, message, stack)
+ {
+ this.status = status;
+ this.message = message;
+ this.stack = stack ? stack : null;
+ };
+
+ Test.prototype.timeout = function()
+ {
+ this.timeout_id = null;
+ this.set_status(this.TIMEOUT, "Test timed out");
+ this.phase = this.phases.HAS_RESULT;
+ this.done();
+ };
+
+ Test.prototype.done = function()
+ {
+ if (this.phase == this.phases.COMPLETE) {
+ return;
+ }
+
+ if (this.phase <= this.phases.STARTED) {
+ this.set_status(this.PASS, null);
+ }
+
+ this.phase = this.phases.COMPLETE;
+
+ clearTimeout(this.timeout_id);
+ tests.result(this);
+ this.cleanup();
+ };
+
+ Test.prototype.cleanup = function() {
+ forEach(this.cleanup_callbacks,
+ function(cleanup_callback) {
+ cleanup_callback();
+ });
+ };
+
+ /*
+ * A RemoteTest object mirrors a Test object on a remote worker. The
+ * associated RemoteWorker updates the RemoteTest object in response to
+ * received events. In turn, the RemoteTest object replicates these events
+ * on the local document. This allows listeners (test result reporting
+ * etc..) to transparently handle local and remote events.
+ */
+ function RemoteTest(clone) {
+ var this_obj = this;
+ Object.keys(clone).forEach(
+ function(key) {
+ this_obj[key] = clone[key];
+ });
+ this.index = null;
+ this.phase = this.phases.INITIAL;
+ this.update_state_from(clone);
+ tests.push(this);
+ }
+
+ RemoteTest.prototype.structured_clone = function() {
+ var clone = {};
+ Object.keys(this).forEach(
+ (function(key) {
+ if (typeof(this[key]) === "object") {
+ clone[key] = merge({}, this[key]);
+ } else {
+ clone[key] = this[key];
+ }
+ }).bind(this));
+ clone.phases = merge({}, this.phases);
+ return clone;
+ };
+
+ RemoteTest.prototype.cleanup = function() {};
+ RemoteTest.prototype.phases = Test.prototype.phases;
+ RemoteTest.prototype.update_state_from = function(clone) {
+ this.status = clone.status;
+ this.message = clone.message;
+ this.stack = clone.stack;
+ if (this.phase === this.phases.INITIAL) {
+ this.phase = this.phases.STARTED;
+ }
+ };
+ RemoteTest.prototype.done = function() {
+ this.phase = this.phases.COMPLETE;
+ }
+
+ /*
+ * A RemoteWorker listens for test events from a worker. These events are
+ * then used to construct and maintain RemoteTest objects that mirror the
+ * tests running on the remote worker.
+ */
+ function RemoteWorker(worker) {
+ this.running = true;
+ this.tests = new Array();
+
+ var this_obj = this;
+ worker.onerror = function(error) { this_obj.worker_error(error); };
+
+ var message_port;
+
+ if (is_service_worker(worker)) {
+ if (window.MessageChannel) {
+ // The ServiceWorker's implicit MessagePort is currently not
+ // reliably accessible from the ServiceWorkerGlobalScope due to
+ // Blink setting MessageEvent.source to null for messages sent
+ // via ServiceWorker.postMessage(). Until that's resolved,
+ // create an explicit MessageChannel and pass one end to the
+ // worker.
+ var message_channel = new MessageChannel();
+ message_port = message_channel.port1;
+ message_port.start();
+ worker.postMessage({type: "connect"}, [message_channel.port2]);
+ } else {
+ // If MessageChannel is not available, then try the
+ // ServiceWorker.postMessage() approach using MessageEvent.source
+ // on the other end.
+ message_port = navigator.serviceWorker;
+ worker.postMessage({type: "connect"});
+ }
+ } else if (is_shared_worker(worker)) {
+ message_port = worker.port;
+ } else {
+ message_port = worker;
+ }
+
+ // Keeping a reference to the worker until worker_done() is seen
+ // prevents the Worker object and its MessageChannel from going away
+ // before all the messages are dispatched.
+ this.worker = worker;
+
+ message_port.onmessage =
+ function(message) {
+ if (this_obj.running && (message.data.type in this_obj.message_handlers)) {
+ this_obj.message_handlers[message.data.type].call(this_obj, message.data);
+ }
+ };
+ }
+
+ RemoteWorker.prototype.worker_error = function(error) {
+ var message = error.message || String(error);
+ var filename = (error.filename ? " " + error.filename: "");
+ // FIXME: Display worker error states separately from main document
+ // error state.
+ this.worker_done({
+ status: {
+ status: tests.status.ERROR,
+ message: "Error in worker" + filename + ": " + message,
+ stack: error.stack
+ }
+ });
+ error.preventDefault();
+ };
+
+ RemoteWorker.prototype.test_state = function(data) {
+ var remote_test = this.tests[data.test.index];
+ if (!remote_test) {
+ remote_test = new RemoteTest(data.test);
+ this.tests[data.test.index] = remote_test;
+ }
+ remote_test.update_state_from(data.test);
+ tests.notify_test_state(remote_test);
+ };
+
+ RemoteWorker.prototype.test_done = function(data) {
+ var remote_test = this.tests[data.test.index];
+ remote_test.update_state_from(data.test);
+ remote_test.done();
+ tests.result(remote_test);
+ };
+
+ RemoteWorker.prototype.worker_done = function(data) {
+ if (tests.status.status === null &&
+ data.status.status !== data.status.OK) {
+ tests.status.status = data.status.status;
+ tests.status.message = data.status.message;
+ tests.status.stack = data.status.stack;
+ }
+ this.running = false;
+ this.worker = null;
+ if (tests.all_done()) {
+ tests.complete();
+ }
+ };
+
+ RemoteWorker.prototype.message_handlers = {
+ test_state: RemoteWorker.prototype.test_state,
+ result: RemoteWorker.prototype.test_done,
+ complete: RemoteWorker.prototype.worker_done
+ };
+
+ /*
+ * Harness
+ */
+
+ function TestsStatus()
+ {
+ this.status = null;
+ this.message = null;
+ this.stack = null;
+ }
+
+ TestsStatus.statuses = {
+ OK:0,
+ ERROR:1,
+ TIMEOUT:2
+ };
+
+ TestsStatus.prototype = merge({}, TestsStatus.statuses);
+
+ TestsStatus.prototype.structured_clone = function()
+ {
+ if (!this._structured_clone) {
+ var msg = this.message;
+ msg = msg ? String(msg) : msg;
+ this._structured_clone = merge({
+ status:this.status,
+ message:msg,
+ stack:this.stack
+ }, TestsStatus.statuses);
+ }
+ return this._structured_clone;
+ };
+
+ function Tests()
+ {
+ this.tests = [];
+ this.num_pending = 0;
+
+ this.phases = {
+ INITIAL:0,
+ SETUP:1,
+ HAVE_TESTS:2,
+ HAVE_RESULTS:3,
+ COMPLETE:4
+ };
+ this.phase = this.phases.INITIAL;
+
+ this.properties = {};
+
+ this.wait_for_finish = false;
+ this.processing_callbacks = false;
+
+ this.allow_uncaught_exception = false;
+
+ this.file_is_test = false;
+
+ this.timeout_multiplier = 1;
+ this.timeout_length = test_environment.test_timeout();
+ this.timeout_id = null;
+
+ this.start_callbacks = [];
+ this.test_state_callbacks = [];
+ this.test_done_callbacks = [];
+ this.all_done_callbacks = [];
+
+ this.pending_workers = [];
+
+ this.status = new TestsStatus();
+
+ var this_obj = this;
+
+ test_environment.add_on_loaded_callback(function() {
+ if (this_obj.all_done()) {
+ this_obj.complete();
+ }
+ });
+
+ this.set_timeout();
+ }
+
+ Tests.prototype.setup = function(func, properties)
+ {
+ if (this.phase >= this.phases.HAVE_RESULTS) {
+ return;
+ }
+
+ if (this.phase < this.phases.SETUP) {
+ this.phase = this.phases.SETUP;
+ }
+
+ this.properties = properties;
+
+ for (var p in properties) {
+ if (properties.hasOwnProperty(p)) {
+ var value = properties[p];
+ if (p == "allow_uncaught_exception") {
+ this.allow_uncaught_exception = value;
+ } else if (p == "explicit_done" && value) {
+ this.wait_for_finish = true;
+ } else if (p == "explicit_timeout" && value) {
+ this.timeout_length = null;
+ if (this.timeout_id)
+ {
+ clearTimeout(this.timeout_id);
+ }
+ } else if (p == "timeout_multiplier") {
+ this.timeout_multiplier = value;
+ }
+ }
+ }
+
+ if (func) {
+ try {
+ func();
+ } catch (e) {
+ this.status.status = this.status.ERROR;
+ this.status.message = String(e);
+ this.status.stack = e.stack ? e.stack : null;
+ }
+ }
+ this.set_timeout();
+ };
+
+ Tests.prototype.set_file_is_test = function() {
+ if (this.tests.length > 0) {
+ throw new Error("Tried to set file as test after creating a test");
+ }
+ this.wait_for_finish = true;
+ this.file_is_test = true;
+ // Create the test, which will add it to the list of tests
+ async_test();
+ };
+
+ Tests.prototype.set_timeout = function() {
+ var this_obj = this;
+ clearTimeout(this.timeout_id);
+ if (this.timeout_length !== null) {
+ this.timeout_id = setTimeout(function() {
+ this_obj.timeout();
+ }, this.timeout_length);
+ }
+ };
+
+ Tests.prototype.timeout = function() {
+ if (this.status.status === null) {
+ this.status.status = this.status.TIMEOUT;
+ }
+ this.complete();
+ };
+
+ Tests.prototype.end_wait = function()
+ {
+ this.wait_for_finish = false;
+ if (this.all_done()) {
+ this.complete();
+ }
+ };
+
+ Tests.prototype.push = function(test)
+ {
+ if (this.phase < this.phases.HAVE_TESTS) {
+ this.start();
+ }
+ this.num_pending++;
+ test.index = this.tests.push(test);
+ this.notify_test_state(test);
+ };
+
+ Tests.prototype.notify_test_state = function(test) {
+ var this_obj = this;
+ forEach(this.test_state_callbacks,
+ function(callback) {
+ callback(test, this_obj);
+ });
+ };
+
+ Tests.prototype.all_done = function() {
+ return (this.tests.length > 0 && test_environment.all_loaded &&
+ this.num_pending === 0 && !this.wait_for_finish &&
+ !this.processing_callbacks &&
+ !this.pending_workers.some(function(w) { return w.running; }));
+ };
+
+ Tests.prototype.start = function() {
+ this.phase = this.phases.HAVE_TESTS;
+ this.notify_start();
+ };
+
+ Tests.prototype.notify_start = function() {
+ var this_obj = this;
+ forEach (this.start_callbacks,
+ function(callback)
+ {
+ callback(this_obj.properties);
+ });
+ };
+
+ Tests.prototype.result = function(test)
+ {
+ if (this.phase > this.phases.HAVE_RESULTS) {
+ return;
+ }
+ this.phase = this.phases.HAVE_RESULTS;
+ this.num_pending--;
+ this.notify_result(test);
+ };
+
+ Tests.prototype.notify_result = function(test) {
+ var this_obj = this;
+ this.processing_callbacks = true;
+ forEach(this.test_done_callbacks,
+ function(callback)
+ {
+ callback(test, this_obj);
+ });
+ this.processing_callbacks = false;
+ if (this_obj.all_done()) {
+ this_obj.complete();
+ }
+ };
+
+ Tests.prototype.complete = function() {
+ if (this.phase === this.phases.COMPLETE) {
+ return;
+ }
+ this.phase = this.phases.COMPLETE;
+ var this_obj = this;
+ this.tests.forEach(
+ function(x)
+ {
+ if (x.phase < x.phases.COMPLETE) {
+ this_obj.notify_result(x);
+ x.cleanup();
+ x.phase = x.phases.COMPLETE;
+ }
+ }
+ );
+ this.notify_complete();
+ };
+
+ Tests.prototype.notify_complete = function() {
+ var this_obj = this;
+ if (this.status.status === null) {
+ this.status.status = this.status.OK;
+ }
+
+ forEach (this.all_done_callbacks,
+ function(callback)
+ {
+ callback(this_obj.tests, this_obj.status);
+ });
+ };
+
+ Tests.prototype.fetch_tests_from_worker = function(worker) {
+ if (this.phase >= this.phases.COMPLETE) {
+ return;
+ }
+
+ this.pending_workers.push(new RemoteWorker(worker));
+ };
+
+ function fetch_tests_from_worker(port) {
+ tests.fetch_tests_from_worker(port);
+ }
+ expose(fetch_tests_from_worker, 'fetch_tests_from_worker');
+
+ function timeout() {
+ if (tests.timeout_length === null) {
+ tests.timeout();
+ }
+ }
+ expose(timeout, 'timeout');
+
+ function add_start_callback(callback) {
+ tests.start_callbacks.push(callback);
+ }
+
+ function add_test_state_callback(callback) {
+ tests.test_state_callbacks.push(callback);
+ }
+
+ function add_result_callback(callback) {
+ tests.test_done_callbacks.push(callback);
+ }
+
+ function add_completion_callback(callback) {
+ tests.all_done_callbacks.push(callback);
+ }
+
+ expose(add_start_callback, 'add_start_callback');
+ expose(add_test_state_callback, 'add_test_state_callback');
+ expose(add_result_callback, 'add_result_callback');
+ expose(add_completion_callback, 'add_completion_callback');
+
+ function remove(array, item) {
+ var index = array.indexOf(item);
+ if (index > -1) {
+ array.splice(index, 1);
+ }
+ }
+
+ function remove_start_callback(callback) {
+ remove(tests.start_callbacks, callback);
+ }
+
+ function remove_test_state_callback(callback) {
+ remove(tests.test_state_callbacks, callback);
+ }
+
+ function remove_result_callback(callback) {
+ remove(tests.test_done_callbacks, callback);
+ }
+
+ function remove_completion_callback(callback) {
+ remove(tests.all_done_callbacks, callback);
+ }
+
+ /*
+ * Output listener
+ */
+
+ function Output() {
+ this.output_document = document;
+ this.output_node = null;
+ this.enabled = settings.output;
+ this.phase = this.INITIAL;
+ }
+
+ Output.prototype.INITIAL = 0;
+ Output.prototype.STARTED = 1;
+ Output.prototype.HAVE_RESULTS = 2;
+ Output.prototype.COMPLETE = 3;
+
+ Output.prototype.setup = function(properties) {
+ if (this.phase > this.INITIAL) {
+ return;
+ }
+
+ //If output is disabled in testharnessreport.js the test shouldn't be
+ //able to override that
+ this.enabled = this.enabled && (properties.hasOwnProperty("output") ?
+ properties.output : settings.output);
+ };
+
+ Output.prototype.init = function(properties) {
+ if (this.phase >= this.STARTED) {
+ return;
+ }
+ if (properties.output_document) {
+ this.output_document = properties.output_document;
+ } else {
+ this.output_document = document;
+ }
+ this.phase = this.STARTED;
+ };
+
+ Output.prototype.resolve_log = function() {
+ var output_document;
+ if (typeof this.output_document === "function") {
+ output_document = this.output_document.apply(undefined);
+ } else {
+ output_document = this.output_document;
+ }
+ if (!output_document) {
+ return;
+ }
+ var node = output_document.getElementById("log");
+ if (!node) {
+ if (!document.body || document.readyState == "loading") {
+ return;
+ }
+ node = output_document.createElement("div");
+ node.id = "log";
+ output_document.body.appendChild(node);
+ }
+ this.output_document = output_document;
+ this.output_node = node;
+ };
+
+ Output.prototype.show_status = function() {
+ if (this.phase < this.STARTED) {
+ this.init();
+ }
+ if (!this.enabled) {
+ return;
+ }
+ if (this.phase < this.HAVE_RESULTS) {
+ this.resolve_log();
+ this.phase = this.HAVE_RESULTS;
+ }
+ var done_count = tests.tests.length - tests.num_pending;
+ if (this.output_node) {
+ if (done_count < 100 ||
+ (done_count < 1000 && done_count % 100 === 0) ||
+ done_count % 1000 === 0) {
+ this.output_node.textContent = "Running, " +
+ done_count + " complete, " +
+ tests.num_pending + " remain";
+ }
+ }
+ };
+
+ Output.prototype.show_results = function (tests, harness_status) {
+ if (this.phase >= this.COMPLETE) {
+ return;
+ }
+ if (!this.enabled) {
+ return;
+ }
+ if (!this.output_node) {
+ this.resolve_log();
+ }
+ this.phase = this.COMPLETE;
+
+ var log = this.output_node;
+ if (!log) {
+ return;
+ }
+ var output_document = this.output_document;
+
+ while (log.lastChild) {
+ log.removeChild(log.lastChild);
+ }
+
+ var harness_url = get_harness_url();
+ if (harness_url !== null) {
+ var stylesheet = output_document.createElementNS(xhtml_ns, "link");
+ stylesheet.setAttribute("rel", "stylesheet");
+ stylesheet.setAttribute("href", harness_url + "testharness.css");
+ var heads = output_document.getElementsByTagName("head");
+ if (heads.length) {
+ heads[0].appendChild(stylesheet);
+ }
+ }
+
+ var status_text_harness = {};
+ status_text_harness[harness_status.OK] = "OK";
+ status_text_harness[harness_status.ERROR] = "Error";
+ status_text_harness[harness_status.TIMEOUT] = "Timeout";
+
+ var status_text = {};
+ status_text[Test.prototype.PASS] = "Pass";
+ status_text[Test.prototype.FAIL] = "Fail";
+ status_text[Test.prototype.TIMEOUT] = "Timeout";
+ status_text[Test.prototype.NOTRUN] = "Not Run";
+
+ var status_number = {};
+ forEach(tests,
+ function(test) {
+ var status = status_text[test.status];
+ if (status_number.hasOwnProperty(status)) {
+ status_number[status] += 1;
+ } else {
+ status_number[status] = 1;
+ }
+ });
+
+ function status_class(status)
+ {
+ return status.replace(/\s/g, '').toLowerCase();
+ }
+
+ var summary_template = ["section", {"id":"summary"},
+ ["h2", {}, "Summary"],
+ function()
+ {
+
+ var status = status_text_harness[harness_status.status];
+ var rv = [["section", {},
+ ["p", {},
+ "Harness status: ",
+ ["span", {"class":status_class(status)},
+ status
+ ],
+ ]
+ ]];
+
+ if (harness_status.status === harness_status.ERROR) {
+ rv[0].push(["pre", {}, harness_status.message]);
+ if (harness_status.stack) {
+ rv[0].push(["pre", {}, harness_status.stack]);
+ }
+ }
+ return rv;
+ },
+ ["p", {}, "Found ${num_tests} tests"],
+ function() {
+ var rv = [["div", {}]];
+ var i = 0;
+ while (status_text.hasOwnProperty(i)) {
+ if (status_number.hasOwnProperty(status_text[i])) {
+ var status = status_text[i];
+ rv[0].push(["div", {"class":status_class(status)},
+ ["label", {},
+ ["input", {type:"checkbox", checked:"checked"}],
+ status_number[status] + " " + status]]);
+ }
+ i++;
+ }
+ return rv;
+ },
+ ];
+
+ log.appendChild(render(summary_template, {num_tests:tests.length}, output_document));
+
+ forEach(output_document.querySelectorAll("section#summary label"),
+ function(element)
+ {
+ on_event(element, "click",
+ function(e)
+ {
+ if (output_document.getElementById("results") === null) {
+ e.preventDefault();
+ return;
+ }
+ var result_class = element.parentNode.getAttribute("class");
+ var style_element = output_document.querySelector("style#hide-" + result_class);
+ var input_element = element.querySelector("input");
+ if (!style_element && !input_element.checked) {
+ style_element = output_document.createElementNS(xhtml_ns, "style");
+ style_element.id = "hide-" + result_class;
+ style_element.textContent = "table#results > tbody > tr."+result_class+"{display:none}";
+ output_document.body.appendChild(style_element);
+ } else if (style_element && input_element.checked) {
+ style_element.parentNode.removeChild(style_element);
+ }
+ });
+ });
+
+ // This use of innerHTML plus manual escaping is not recommended in
+ // general, but is necessary here for performance. Using textContent
+ // on each individual <td> adds tens of seconds of execution time for
+ // large test suites (tens of thousands of tests).
+ function escape_html(s)
+ {
+ return s.replace(/\&/g, "&amp;")
+ .replace(/</g, "&lt;")
+ .replace(/"/g, "&quot;")
+ .replace(/'/g, "&#39;");
+ }
+
+ function has_assertions()
+ {
+ for (var i = 0; i < tests.length; i++) {
+ if (tests[i].properties.hasOwnProperty("assert")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function get_assertion(test)
+ {
+ if (test.properties.hasOwnProperty("assert")) {
+ if (Array.isArray(test.properties.assert)) {
+ return test.properties.assert.join(' ');
+ }
+ return test.properties.assert;
+ }
+ return '';
+ }
+
+ log.appendChild(document.createElementNS(xhtml_ns, "section"));
+ var assertions = has_assertions();
+ var html = "<h2>Details</h2><table id='results' " + (assertions ? "class='assertions'" : "" ) + ">" +
+ "<thead><tr><th>Result</th><th>Test Name</th>" +
+ (assertions ? "<th>Assertion</th>" : "") +
+ "<th>Message</th></tr></thead>" +
+ "<tbody>";
+ for (var i = 0; i < tests.length; i++) {
+ html += '<tr class="' +
+ escape_html(status_class(status_text[tests[i].status])) +
+ '"><td>' +
+ escape_html(status_text[tests[i].status]) +
+ "</td><td>" +
+ escape_html(tests[i].name) +
+ "</td><td>" +
+ (assertions ? escape_html(get_assertion(tests[i])) + "</td><td>" : "") +
+ escape_html(tests[i].message ? tests[i].message : " ") +
+ (tests[i].stack ? "<pre>" +
+ escape_html(tests[i].stack) +
+ "</pre>": "") +
+ "</td></tr>";
+ }
+ html += "</tbody></table>";
+ try {
+ log.lastChild.innerHTML = html;
+ } catch (e) {
+ log.appendChild(document.createElementNS(xhtml_ns, "p"))
+ .textContent = "Setting innerHTML for the log threw an exception.";
+ log.appendChild(document.createElementNS(xhtml_ns, "pre"))
+ .textContent = html;
+ }
+ };
+
+ /*
+ * Template code
+ *
+ * A template is just a javascript structure. An element is represented as:
+ *
+ * [tag_name, {attr_name:attr_value}, child1, child2]
+ *
+ * the children can either be strings (which act like text nodes), other templates or
+ * functions (see below)
+ *
+ * A text node is represented as
+ *
+ * ["{text}", value]
+ *
+ * String values have a simple substitution syntax; ${foo} represents a variable foo.
+ *
+ * It is possible to embed logic in templates by using a function in a place where a
+ * node would usually go. The function must either return part of a template or null.
+ *
+ * In cases where a set of nodes are required as output rather than a single node
+ * with children it is possible to just use a list
+ * [node1, node2, node3]
+ *
+ * Usage:
+ *
+ * render(template, substitutions) - take a template and an object mapping
+ * variable names to parameters and return either a DOM node or a list of DOM nodes
+ *
+ * substitute(template, substitutions) - take a template and variable mapping object,
+ * make the variable substitutions and return the substituted template
+ *
+ */
+
+ function is_single_node(template)
+ {
+ return typeof template[0] === "string";
+ }
+
+ function substitute(template, substitutions)
+ {
+ if (typeof template === "function") {
+ var replacement = template(substitutions);
+ if (!replacement) {
+ return null;
+ }
+
+ return substitute(replacement, substitutions);
+ }
+
+ if (is_single_node(template)) {
+ return substitute_single(template, substitutions);
+ }
+
+ return filter(map(template, function(x) {
+ return substitute(x, substitutions);
+ }), function(x) {return x !== null;});
+ }
+
+ function substitute_single(template, substitutions)
+ {
+ var substitution_re = /\$\{([^ }]*)\}/g;
+
+ function do_substitution(input) {
+ var components = input.split(substitution_re);
+ var rv = [];
+ for (var i = 0; i < components.length; i += 2) {
+ rv.push(components[i]);
+ if (components[i + 1]) {
+ rv.push(String(substitutions[components[i + 1]]));
+ }
+ }
+ return rv;
+ }
+
+ function substitute_attrs(attrs, rv)
+ {
+ rv[1] = {};
+ for (var name in template[1]) {
+ if (attrs.hasOwnProperty(name)) {
+ var new_name = do_substitution(name).join("");
+ var new_value = do_substitution(attrs[name]).join("");
+ rv[1][new_name] = new_value;
+ }
+ }
+ }
+
+ function substitute_children(children, rv)
+ {
+ for (var i = 0; i < children.length; i++) {
+ if (children[i] instanceof Object) {
+ var replacement = substitute(children[i], substitutions);
+ if (replacement !== null) {
+ if (is_single_node(replacement)) {
+ rv.push(replacement);
+ } else {
+ extend(rv, replacement);
+ }
+ }
+ } else {
+ extend(rv, do_substitution(String(children[i])));
+ }
+ }
+ return rv;
+ }
+
+ var rv = [];
+ rv.push(do_substitution(String(template[0])).join(""));
+
+ if (template[0] === "{text}") {
+ substitute_children(template.slice(1), rv);
+ } else {
+ substitute_attrs(template[1], rv);
+ substitute_children(template.slice(2), rv);
+ }
+
+ return rv;
+ }
+
+ function make_dom_single(template, doc)
+ {
+ var output_document = doc || document;
+ var element;
+ if (template[0] === "{text}") {
+ element = output_document.createTextNode("");
+ for (var i = 1; i < template.length; i++) {
+ element.data += template[i];
+ }
+ } else {
+ element = output_document.createElementNS(xhtml_ns, template[0]);
+ for (var name in template[1]) {
+ if (template[1].hasOwnProperty(name)) {
+ element.setAttribute(name, template[1][name]);
+ }
+ }
+ for (var i = 2; i < template.length; i++) {
+ if (template[i] instanceof Object) {
+ var sub_element = make_dom(template[i]);
+ element.appendChild(sub_element);
+ } else {
+ var text_node = output_document.createTextNode(template[i]);
+ element.appendChild(text_node);
+ }
+ }
+ }
+
+ return element;
+ }
+
+ function make_dom(template, substitutions, output_document)
+ {
+ if (is_single_node(template)) {
+ return make_dom_single(template, output_document);
+ }
+
+ return map(template, function(x) {
+ return make_dom_single(x, output_document);
+ });
+ }
+
+ function render(template, substitutions, output_document)
+ {
+ return make_dom(substitute(template, substitutions), output_document);
+ }
+
+ /*
+ * Utility funcions
+ */
+ function assert(expected_true, function_name, description, error, substitutions)
+ {
+ if (tests.tests.length === 0) {
+ tests.set_file_is_test();
+ }
+ if (expected_true !== true) {
+ var msg = make_message(function_name, description,
+ error, substitutions);
+ throw new AssertionError(msg);
+ }
+ }
+
+ function AssertionError(message)
+ {
+ this.message = message;
+ this.stack = this.get_stack();
+ }
+
+ AssertionError.prototype = Object.create(Error.prototype);
+
+ AssertionError.prototype.get_stack = function() {
+ var stack = new Error().stack;
+ // IE11 does not initialize 'Error.stack' until the object is thrown.
+ if (!stack) {
+ try {
+ throw new Error();
+ } catch (e) {
+ stack = e.stack;
+ }
+ }
+
+ var lines = stack.split("\n");
+
+ // Create a pattern to match stack frames originating within testharness.js. These include the
+ // script URL, followed by the line/col (e.g., '/resources/testharness.js:120:21').
+ // Escape the URL per http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+ // in case it contains RegExp characters.
+ var script_url = get_script_url();
+ var re_text = script_url ? script_url.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') : "\\btestharness.js";
+ var re = new RegExp(re_text + ":\\d+:\\d+");
+
+ // Some browsers include a preamble that specifies the type of the error object. Skip this by
+ // advancing until we find the first stack frame originating from testharness.js.
+ var i = 0;
+ while (!re.test(lines[i]) && i < lines.length) {
+ i++;
+ }
+
+ // Then skip the top frames originating from testharness.js to begin the stack at the test code.
+ while (re.test(lines[i]) && i < lines.length) {
+ i++;
+ }
+
+ // Paranoid check that we didn't skip all frames. If so, return the original stack unmodified.
+ if (i >= lines.length) {
+ return stack;
+ }
+
+ return lines.slice(i).join("\n");
+ }
+
+ function make_message(function_name, description, error, substitutions)
+ {
+ for (var p in substitutions) {
+ if (substitutions.hasOwnProperty(p)) {
+ substitutions[p] = format_value(substitutions[p]);
+ }
+ }
+ var node_form = substitute(["{text}", "${function_name}: ${description}" + error],
+ merge({function_name:function_name,
+ description:(description?description + " ":"")},
+ substitutions));
+ return node_form.slice(1).join("");
+ }
+
+ function filter(array, callable, thisObj) {
+ var rv = [];
+ for (var i = 0; i < array.length; i++) {
+ if (array.hasOwnProperty(i)) {
+ var pass = callable.call(thisObj, array[i], i, array);
+ if (pass) {
+ rv.push(array[i]);
+ }
+ }
+ }
+ return rv;
+ }
+
+ function map(array, callable, thisObj)
+ {
+ var rv = [];
+ rv.length = array.length;
+ for (var i = 0; i < array.length; i++) {
+ if (array.hasOwnProperty(i)) {
+ rv[i] = callable.call(thisObj, array[i], i, array);
+ }
+ }
+ return rv;
+ }
+
+ function extend(array, items)
+ {
+ Array.prototype.push.apply(array, items);
+ }
+
+ function forEach(array, callback, thisObj)
+ {
+ for (var i = 0; i < array.length; i++) {
+ if (array.hasOwnProperty(i)) {
+ callback.call(thisObj, array[i], i, array);
+ }
+ }
+ }
+
+ function merge(a,b)
+ {
+ var rv = {};
+ var p;
+ for (p in a) {
+ rv[p] = a[p];
+ }
+ for (p in b) {
+ rv[p] = b[p];
+ }
+ return rv;
+ }
+
+ function expose(object, name)
+ {
+ var components = name.split(".");
+ var target = test_environment.global_scope();
+ for (var i = 0; i < components.length - 1; i++) {
+ if (!(components[i] in target)) {
+ target[components[i]] = {};
+ }
+ target = target[components[i]];
+ }
+ target[components[components.length - 1]] = object;
+ }
+
+ function is_same_origin(w) {
+ try {
+ 'random_prop' in w;
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ /** Returns the 'src' URL of the first <script> tag in the page to include the file 'testharness.js'. */
+ function get_script_url()
+ {
+ if (!('document' in self)) {
+ return undefined;
+ }
+
+ var scripts = document.getElementsByTagName("script");
+ for (var i = 0; i < scripts.length; i++) {
+ var src;
+ if (scripts[i].src) {
+ src = scripts[i].src;
+ } else if (scripts[i].href) {
+ //SVG case
+ src = scripts[i].href.baseVal;
+ }
+
+ var matches = src && src.match(/^(.*\/|)testharness\.js$/);
+ if (matches) {
+ return src;
+ }
+ }
+ return undefined;
+ }
+
+ /** Returns the URL path at which the files for testharness.js are assumed to reside (e.g., '/resources/').
+ The path is derived from inspecting the 'src' of the <script> tag that included 'testharness.js'. */
+ function get_harness_url()
+ {
+ var script_url = get_script_url();
+
+ // Exclude the 'testharness.js' file from the returned path, but '+ 1' to include the trailing slash.
+ return script_url ? script_url.slice(0, script_url.lastIndexOf('/') + 1) : undefined;
+ }
+
+ function supports_post_message(w)
+ {
+ var supports;
+ var type;
+ // Given IE implements postMessage across nested iframes but not across
+ // windows or tabs, you can't infer cross-origin communication from the presence
+ // of postMessage on the current window object only.
+ //
+ // Touching the postMessage prop on a window can throw if the window is
+ // not from the same origin AND post message is not supported in that
+ // browser. So just doing an existence test here won't do, you also need
+ // to wrap it in a try..cacth block.
+ try {
+ type = typeof w.postMessage;
+ if (type === "function") {
+ supports = true;
+ }
+
+ // IE8 supports postMessage, but implements it as a host object which
+ // returns "object" as its `typeof`.
+ else if (type === "object") {
+ supports = true;
+ }
+
+ // This is the case where postMessage isn't supported AND accessing a
+ // window property across origins does NOT throw (e.g. old Safari browser).
+ else {
+ supports = false;
+ }
+ } catch (e) {
+ // This is the case where postMessage isn't supported AND accessing a
+ // window property across origins throws (e.g. old Firefox browser).
+ supports = false;
+ }
+ return supports;
+ }
+
+ /**
+ * Setup globals
+ */
+
+ var tests = new Tests();
+
+ addEventListener("error", function(e) {
+ if (tests.file_is_test) {
+ var test = tests.tests[0];
+ if (test.phase >= test.phases.HAS_RESULT) {
+ return;
+ }
+ test.set_status(test.FAIL, e.message, e.stack);
+ test.phase = test.phases.HAS_RESULT;
+ test.done();
+ done();
+ } else if (!tests.allow_uncaught_exception) {
+ tests.status.status = tests.status.ERROR;
+ tests.status.message = e.message;
+ tests.status.stack = e.stack;
+ }
+ });
+
+ test_environment.on_tests_ready();
+
+})();
+// vim: set expandtab shiftwidth=4 tabstop=4:
diff --git a/testing/web-platform/tests/resources/testharnessreport.js b/testing/web-platform/tests/resources/testharnessreport.js
new file mode 100644
index 000000000..79559773f
--- /dev/null
+++ b/testing/web-platform/tests/resources/testharnessreport.js
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var props = {output:%(output)d,
+ explicit_timeout: true,
+ message_events: ["completion"]};
+
+if (window.opener && "timeout_multiplier" in window.opener) {
+ props["timeout_multiplier"] = window.opener.timeout_multiplier;
+}
+
+if (window.opener && window.opener.explicit_timeout) {
+ props["explicit_timeout"] = window.opener.explicit_timeout;
+}
+
+setup(props);
diff --git a/testing/web-platform/tests/resources/webidl2/.gitignore b/testing/web-platform/tests/resources/webidl2/.gitignore
new file mode 100644
index 000000000..1d72980cd
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/.gitignore
@@ -0,0 +1,4 @@
+scratch
+node_modules
+lib-cov
+browser-tests.html
diff --git a/testing/web-platform/tests/resources/webidl2/.gitmodules b/testing/web-platform/tests/resources/webidl2/.gitmodules
new file mode 100644
index 000000000..a3f5485cd
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "test/widlproc"]
+ path = test/widlproc
+ url = https://github.com/dontcallmedom/widlproc.git
diff --git a/testing/web-platform/tests/resources/webidl2/.travis.yml b/testing/web-platform/tests/resources/webidl2/.travis.yml
new file mode 100644
index 000000000..6e5919de3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+ - "0.10"
diff --git a/testing/web-platform/tests/resources/webidl2/LICENSE b/testing/web-platform/tests/resources/webidl2/LICENSE
new file mode 100644
index 000000000..fd21d439b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Robin Berjon
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/testing/web-platform/tests/resources/webidl2/README.md b/testing/web-platform/tests/resources/webidl2/README.md
new file mode 100644
index 000000000..f7d03fcde
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/README.md
@@ -0,0 +1,760 @@
+
+# WebIDL 2
+
+[![NPM version](https://badge.fury.io/js/webidl2.png)](http://badge.fury.io/js/webidl2)
+
+Purpose
+=======
+
+This is a parser for the [WebIDL](http://dev.w3.org/2006/webapi/WebIDL/) language. If
+you don't know what that is, then you probably don't need it. It is meant to be used
+both in Node and in the browser (the parser likely works in other JS environments, but
+not the test suite).
+
+What of v1?
+-----------
+There was a previous incarnation of this project. I had written it in the most quick
+and dirty manner that was handy because I required it as a dependency in an experiment.
+As these things tend to happen, some people started using that, which then had to be
+maintained. But since it was not built on solid foundations, it was painful to keep
+up to date with the specification, which is a bit of a moving target.
+
+So I started from scratch. Compared to the previous version (which used a parser generator)
+this one is about 6x less code (which translates to 4x smaller minified or 2x smaller
+minizipped) and 4x faster. The test suite is reasonably complete (95% coverage), much more
+than previously. This version is up to date with WebIDL, rather than a couple years' behind.
+It also has *far* better error reporting.
+
+The AST you get from parsing is very similar to the one you got in v1, but some adjustments
+have been made in order to be more systematic, and to map better to what's actually in the spec
+now. If you used v1, you will need to tweak your code but the result ought to be simpler and
+you ought to be able to be a fair bit less defensive against irregularities in the way
+information is represented.
+
+Installation
+============
+
+Just the usual. For Node:
+
+ npm install webidl2
+
+In the browser:
+
+ <script src='webidl2.js'></script>
+
+Documentation
+=============
+
+The API to WebIDL2 is trivial: you parse a string of WebIDL and it returns a syntax tree.
+
+Parsing
+-------
+In Node, that happens with:
+
+ var WebIDL2 = require("webidl2");
+ var tree = WebIDL2.parse("string of WebIDL");
+
+In the browser:
+
+ <script src='webidl2.js'></script>
+ <script>
+ var tree = WebIDL2.parse("string of WebIDL");
+ </script>
+
+Advanced Parsing
+----------------
+
+`parse()` can optionally accept a second parameter, an options object, which can be used to
+modify parsing behavior.
+
+The following options are recognized:
+```javascript
+{
+ allowNestedTypedefs: false #
+}
+```
+And their meanings are as follows:
+
+* `allowNestedTypedefs`: Boolean indicating whether the parser should accept `typedef`s as valid members of `interface`s. This is non-standard syntax and therefore the default is `false`.
+
+Errors
+------
+When there is a syntax error in the WebIDL, it throws an exception object with the following
+properties:
+
+* `message`: the error message
+* `line`: the line at which the error occurred.
+* `input`: a short peek at the text at the point where the error happened
+* `tokens`: the five tokens at the point of error, as understood by the tokeniser
+ (this is the same content as `input`, but seen from the tokeniser's point of view)
+
+The exception also has a `toString()` method that hopefully should produce a decent
+error message.
+
+AST (Abstract Syntax Tree)
+--------------------------
+The `parse()` method returns a tree object representing the parse tree of the IDL.
+Comment and white space are not represented in the AST.
+
+The root of this object is always an array of definitions (where definitions are
+any of interfaces, exceptions, callbacks, etc. — anything that can occur at the root
+of the IDL).
+
+### IDL Type
+
+This structure is used in many other places (operation return types, argument types, etc.).
+It captures a WebIDL type with a number of options. Types look like this and are typically
+attached to a field called `idlType`:
+
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ }
+
+Where the fields are as follows:
+
+* `sequence`: Boolean indicating whether this is a sequence or not. Deprecated. Use
+ `generic` instead.
+* `generic`: String indicating the generic type (e.g. "Promise", "sequence"). `null`
+ otherwise.
+* `nullable`: Boolean indicating whether this is nullable or not.
+* `array`: Either `false` to indicate that it is not an array, or a number for the level of
+ array nesting.
+* `union`: Boolean indicating whether this is a union type or not.
+* `idlType`: Can be different things depending on context. In most cases, this will just
+ be a string with the type name. But the reason this field isn't called "typeName" is
+ because it can take more complex values. If the type is a union, then this contains an
+ array of the types it unites. If it is a generic type, it contains the IDL type
+ description for the type in the sequence, the eventual value of the promise, etc.
+
+#### Interactions between `nullable` and `array`
+
+A more complex data model for our AST would likely represent `Foo[][][]` as a series of
+nested types four levels deep with three anonymous array types eventually containing a
+`Foo` type. But experience shows that such structures are cumbersome to use, and so we
+have a simpler model in which the depth of the array is specified with the `array` field.
+
+This is all fine and well, and in the vast majority of cases is actually simpler. But it
+does run afoul of cases in which it is necessary to distinguish between `Foo[][][]?`,
+`Foo?[][][]`, `Foo[][]?[]`, or even `Foo?[]?[]?[]?`.
+
+For this, when a type is an array type an additional `nullableArray` field is made available
+that captures which of the arrays contain nullable elements. It contains booleans that are
+true if the given array depth contains nullable elements, and false otherwise (mapping that to
+the syntax, and item is true if there is a `?` preceding the `[]`). These examples ought to
+clarify the model:
+
+ Foo[][][]?
+ -> nullable: true
+ -> nullableArray: [false, false, false]
+ Foo?[][][]
+ -> nullable: false
+ -> nullableArray: [true, false, false]
+ Foo[][]?[]
+ -> nullable: false
+ -> nullableArray: [false, false, true]
+ Foo?[]?[]?[]?
+ -> nullable: true
+ -> nullableArray: [true, true, true]
+
+Of particular importance, please note that the overall type is only `nullable` if there is
+a `?` at the end.
+
+### Interface
+Interfaces look like this:
+
+ {
+ "type": "interface",
+ "name": "Animal",
+ "partial": false,
+ "members": [...],
+ "inheritance": null,
+ "extAttrs": [...]
+ },
+ {
+ "type": "interface",
+ "name": "Human",
+ "partial": false,
+ "members": [...],
+ "inheritance": "Animal",
+ "extAttrs": [...]
+ }
+
+The fields are as follows:
+
+* `type`: Always "interface".
+* `name`: The name of the interface
+* `partial`: A boolean indicating whether it's a partial interface.
+* `members`: An array of interface members (attributes, operations, etc.). Empty if there are none.
+* `inheritance`: A string giving the name of an interface this one inherits from, `null` otherwise.
+ **NOTE**: In v1 this was an array, but multiple inheritance is no longer supported so this didn't make
+ sense.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Callback Interfaces
+
+These are captured by the same structure as [Interfaces](#interface) except that
+their `type` field is "callback interface".
+
+### Callback
+
+A callback looks like this:
+
+ {
+ "type": "callback",
+ "name": "AsyncOperationCallback",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "arguments": [...],
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "callback".
+* `name`: The name of the callback.
+* `idlType`: An [IDL Type](#idl-type) describing what the callback returns.
+* `arguments`: A list of [arguments](#arguments), as in function paramters.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Dictionary
+
+A dictionary looks like this:
+
+ {
+ "type": "dictionary",
+ "name": "PaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "fillPattern",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "string",
+ "value": "black"
+ }
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "dictionary".
+* `name`: The dictionary name.
+* `partial`: Boolean indicating whether it's a partial dictionary.
+* `members`: An array of members (see below).
+* `inheritance`: A string indicating which dictionary is being inherited from, `null` otherwise.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+All the members are fields as follows:
+
+* `type`: Always "field".
+* `name`: The name of the field.
+* `required`: Boolean indicating whether this is a [required](https://heycam.github.io/webidl/#required-dictionary-member) field.
+* `idlType`: An [IDL Type](#idl-type) describing what field's type.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+* `default`: A [default value](#default-and-const-values), absent if there is none.
+
+### Exception
+
+An exception looks like this:
+
+ {
+ "type": "exception",
+ "name": "HierarchyRequestError",
+ "members": [
+ {
+ "type": "field",
+ "name": "code",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "DOMException",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "exception".
+* `name`: The exception name.
+* `members`: An array of members (constants or fields, where fields are described below).
+* `inheritance`: A string indicating which exception is being inherited from, `null` otherwise.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+Members that aren't [constants](#constants) have the following fields:
+
+* `type`: Always "field".
+* `name`: The field's name.
+* `idlType`: An [IDL Type](#idl-type) describing what field's type.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Enum
+
+An enum looks like this:
+
+ {
+ "type": "enum",
+ "name": "MealType",
+ "values": [
+ "rice",
+ "noodles",
+ "other"
+ ],
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "enum".
+* `name`: The enum's name.
+* `value`: An array of values (strings).
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Typedef
+
+A typedef looks like this:
+
+ {
+ "type": "typedef",
+ "typeExtAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ }
+ },
+ "name": "PointSequence",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "typedef".
+* `name`: The typedef's name.
+* `idlType`: An [IDL Type](#idl-type) describing what typedef's type.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+* `typeExtAttrs`: A list of [extended attributes](#extended-attributes) that apply to the
+type rather than to the typedef as a whole.
+
+### Implements
+
+An implements definition looks like this:
+
+ {
+ "type": "implements",
+ "target": "Node",
+ "implements": "EventTarget",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "implements".
+* `target`: The interface that implements another.
+* `implements`: The interface that is being implemented by the target.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Operation Member
+
+An operation looks like this:
+
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "intersection",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ],
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "operation".
+* `getter`: True if a getter operation.
+* `setter`: True if a setter operation.
+* `creator`: True if a creator operation.
+* `deleter`: True if a deleter operation.
+* `legacycaller`: True if a legacycaller operation.
+* `static`: True if a static operation.
+* `stringifier`: True if a stringifier operation.
+* `idlType`: An [IDL Type](#idl-type) of what the operation returns. If a stringifier, may be absent.
+* `name`: The name of the operation. If a stringifier, may be `null`.
+* `arguments`: An array of [arguments](#arguments) for the operation.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Attribute Member
+
+An attribute member looks like this:
+
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "RegExp"
+ },
+ "name": "regexp",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "attribute".
+* `name`: The attribute's name.
+* `static`: True if it's a static attribute.
+* `stringifier`: True if it's a stringifier attribute.
+* `inherit`: True if it's an inherit attribute.
+* `readonly`: True if it's a read-only attribute.
+* `idlType`: An [IDL Type](#idl-type) for the attribute.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Constant Member
+
+A constant member looks like this:
+
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "boolean",
+ "name": "DEBUG",
+ "value": {
+ "type": "boolean",
+ "value": false
+ },
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "const".
+* `nullable`: Whether its type is nullable.
+* `idlType`: The type of the constant (a simple type, the type name).
+* `name`: The name of the constant.
+* `value`: The constant value as described by [Const Values](#default-and-const-values)
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Serializer Member
+
+Serializers come in many shapes, which are best understood by looking at the
+examples below that map the IDL to the produced AST.
+
+ // serializer;
+ {
+ "type": "serializer",
+ "extAttrs": []
+ }
+
+ // serializer DOMString serialize();
+ {
+ "type": "serializer",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "operation": {
+ "name": "serialize",
+ "arguments": []
+ },
+ "extAttrs": []
+ }
+
+ // serializer = { from, to, amount, description };
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "from",
+ "to",
+ "amount",
+ "description"
+ ],
+ "extAttrs": []
+ }
+
+ // serializer = number;
+ {
+ "type": "serializer",
+ "name": "number",
+ "extAttrs": []
+ }
+
+ // serializer = [ name, number ];
+ {
+ "type": "serializer",
+ "patternList": true,
+ "names": [
+ "name",
+ "number"
+ ],
+ "extAttrs": []
+ }
+
+The common fields are as follows:
+
+* `type`: Always "serializer".
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+For a simple serializer, that's all there is. If the serializer is an operation, it will
+have:
+
+* `idlType`: An [IDL Type](#idl-type) describing what the serializer returns.
+* `operation`: An object with the following fields:
+ * `name`: The name of the operation.
+ * `arguments`: An array of [arguments](#arguments) for the operation.
+
+If the serializer is a pattern map:
+
+* `patternMap`: Always true.
+* `names`: An array of names in the pattern map.
+
+If the serializer is a pattern list:
+
+* `patternList`: Always true.
+* `names`: An array of names in the pattern list.
+
+Finally, if the serializer is a named serializer:
+
+* `name`: The serializer's name.
+
+### Iterator Member
+
+Iterator members look like this
+
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session2"
+ },
+ "iteratorObject": "SessionIterator",
+ "extAttrs": []
+ }
+
+* `type`: Always "iterator".
+* `iteratorObject`: The string on the right-hand side; absent if there isn't one.
+* the rest: same as on [operations](#operation-member).
+
+### Arguments
+
+The arguments (e.g. for an operation) look like this:
+
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ]
+
+The fields are as follows:
+
+* `optional`: True if the argument is optional.
+* `variadic`: True if the argument is variadic.
+* `idlType`: An [IDL Type](#idl-type) describing the type of the argument.
+* `name`: The argument's name.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Extended Attributes
+
+Extended attributes are arrays of items that look like this:
+
+ "extAttrs": [
+ {
+ "name": "TreatNullAs",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "EmptyString"
+ }
+ }
+ ]
+
+The fields are as follows:
+
+* `name`: The extended attribute's name.
+* `arguments`: If the extended attribute takes arguments (e.g. `[Foo()]`) or if
+ its right-hand side does (e.g. `[NamedConstructor=Name(DOMString blah)]`) they
+ are listed here. Note that an empty arguments list will produce an empty array,
+ whereas the lack thereof will yield a `null`. If there is an `rhs` field then
+ they are the right-hand side's arguments, otherwise they apply to the extended
+ attribute directly.
+* `rhs`: If there is a right-hand side, this will capture its `type` (which can be
+ "identifier" or "identifier-list") and its `value`.
+* `typePair`: If the extended attribute is a `MapClass` this will capture the
+ map's key type and value type respectively.
+
+### Default and Const Values
+
+Dictionary fields and operation arguments can take default values, and constants take
+values, all of which have the following fields:
+
+* `type`: One of string, number, boolean, null, Infinity, NaN, or sequence.
+
+For string, number, boolean, and sequence:
+
+* `value`: The value of the given type. For sequence, the only possible value is `[]`.
+
+For Infinity:
+
+* `negative`: Boolean indicating whether this is negative Infinity or not.
+
+### `iterable<>`, `legacyiterable<>`, `maplike<>`, `setlike<>` declarations
+
+These appear as members of interfaces that look like this:
+
+ {
+ "type": "maplike", // or "legacyiterable" / "iterable" / "setlike"
+ "idlType": /* One or two types */,
+ "readonly": false, // only for maplike and setlike
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always one of "iterable", "legacyiterable", "maplike" or "setlike".
+* `idlType`: An [IDL Type](#idl-type) (or an array of two types) representing the declared type arguments.
+* `readonly`: Whether the maplike or setlike is declared as read only.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+
+Testing
+=======
+
+In order to run the tests you need to ensure that the widlproc submodule inside `test` is
+initialised and up to date:
+
+ git submodule init
+ git submodule update
+
+Running
+-------
+The test runs with mocha and expect.js. Normally, running mocha in the root directory
+should be enough once you're set up.
+
+Coverage
+--------
+Current test coverage, as documented in `coverage.html`, is 95%. You can run your own
+coverage analysis with:
+
+ jscoverage lib lib-cov
+
+That will create the lib-cov directory with instrumented code; the test suite knows
+to use that if needed. You can then run the tests with:
+
+ JSCOV=1 mocha --reporter html-cov > coverage.html
+
+Note that I've been getting weirdly overescaped results from the html-cov reporter,
+so you might wish to try this instead:
+
+ JSCOV=1 mocha --reporter html-cov | sed "s/&lt;/</g" | sed "s/&gt;/>/g" | sed "s/&quot;/\"/g" > coverage.html
+
+Browser tests
+-------------
+In order to test in the browser, get inside `test/web` and run `make-web-tests.js`. This
+will generate a `browser-tests.html` file that you can open in a browser. As of this
+writing tests pass in the latest Firefox, Chrome, Opera, and Safari. Testing on IE
+and older versions will happen progressively.
+
+TODO
+====
+
+* add some tests to address coverage limitations
+* add a push API for processors that need to process things like comments
diff --git a/testing/web-platform/tests/resources/webidl2/coverage.html b/testing/web-platform/tests/resources/webidl2/coverage.html
new file mode 100644
index 000000000..46e7ed324
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/coverage.html
@@ -0,0 +1,341 @@
+<!DOCTYPE html><html><head><title>Coverage</title><script>
+
+headings = [];
+
+onload = function(){
+ headings = document.querySelectorAll('h2');
+};
+
+onscroll = function(e){
+ var heading = find(window.scrollY);
+ if (!heading) return;
+ var links = document.querySelectorAll('#menu a')
+ , link;
+
+ for (var i = 0, len = links.length; i < len; ++i) {
+ link = links[i];
+ link.className = link.getAttribute('href') == '#' + heading.id
+ ? 'active'
+ : '';
+ }
+};
+
+function find(y) {
+ var i = headings.length
+ , heading;
+
+ while (i--) {
+ heading = headings[i];
+ if (y >= heading.offsetTop) {
+ return heading;
+ }
+ }
+}
+</script>
+<style>
+
+body {
+ font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ margin: 0;
+ color: #2C2C2C;
+ border-top: 2px solid #ddd;
+}
+
+#coverage {
+ padding: 60px;
+}
+
+h1 a {
+ color: inherit;
+ font-weight: inherit;
+}
+
+h1 a:hover {
+ text-decoration: none;
+}
+
+.onload h1 {
+ opacity: 1;
+}
+
+h2 {
+ width: 80%;
+ margin-top: 80px;
+ margin-bottom: 0;
+ font-weight: 100;
+ letter-spacing: 1px;
+ border-bottom: 1px solid #eee;
+}
+
+a {
+ color: #8A6343;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+ul {
+ margin-top: 20px;
+ padding: 0 15px;
+ width: 100%;
+}
+
+ul li {
+ float: left;
+ width: 40%;
+ margin-top: 5px;
+ margin-right: 60px;
+ list-style: none;
+ border-bottom: 1px solid #eee;
+ padding: 5px 0;
+ font-size: 12px;
+}
+
+ul::after {
+ content: '.';
+ height: 0;
+ display: block;
+ visibility: hidden;
+ clear: both;
+}
+
+code {
+ font: 12px monaco, monospace;
+}
+
+pre {
+ margin: 30px;
+ padding: 30px;
+ border: 1px solid #eee;
+ border-bottom-color: #ddd;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ -webkit-box-shadow: inset 0 0 10px #eee;
+ -moz-box-shadow: inset 0 0 10px #eee;
+ overflow-x: auto;
+}
+
+img {
+ margin: 30px;
+ padding: 1px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -webkit-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
+ -moz-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
+ max-width: 100%;
+}
+
+footer {
+ background: #eee;
+ width: 100%;
+ padding: 50px 0;
+ text-align: right;
+ border-top: 1px solid #ddd;
+}
+
+footer span {
+ display: block;
+ margin-right: 30px;
+ color: #888;
+ font-size: 12px;
+}
+
+#menu {
+ position: fixed;
+ font-size: 12px;
+ overflow-y: auto;
+ top: 0;
+ right: 0;
+ margin: 0;
+ height: 100%;
+ padding: 15px 0;
+ text-align: right;
+ border-left: 1px solid #eee;
+ -moz-box-shadow: 0 0 2px #888
+ , inset 5px 0 20px rgba(0,0,0,.5)
+ , inset 5px 0 3px rgba(0,0,0,.3);
+ -webkit-box-shadow: 0 0 2px #888
+ , inset 5px 0 20px rgba(0,0,0,.5)
+ , inset 5px 0 3px rgba(0,0,0,.3);
+ -webkit-font-smoothing: antialiased;
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAMAAAAOARRQAAABelBMVEUjJSU6OzshIyM5OjoqKy02NjgsLS01NTYjJCUzNTUgISMlJSc0NTUvMDA6PDwlJyg1NjYoKis2NjYrLS02ODkpKyw0NDYrLC04ODovLzA4Ojo0NDUtLy86OjwjIyU4OTosLS82ODgtLS8hIyQvMTEnKCooKSsrKy0qLCwkJSUnKCkrLCwpKiwwMjIxMzMqLC0tLS0pKissLC00NTYwMDIwMTQpKysoKSovMDEtLzA2OTkxMzUrKywvLy8qKyszNTY5OzsqKiw6OjswMDExNDUoKiozNDUvMDIyNDY1Njg2Njk5OTozMzU0NjY4ODkiIyUiIyQ4OTkuMDEmKCowMjQwMTErLS4qKywwMTMhIiMpKiopKy0tLjAkJScxNDQvLzExNDYyNDQmKCk5OTslJig5OjskJSYxMzQrLS8gISIwMTIoKCk1NTUlJSUnJygwMDA4ODgiIiMhISI8PDw6Ojo5OTkpKSojIyQ7OzsyMjIpKSssLCw6Ozw1NjlrfLakAAAg2UlEQVR42jR6i3ea6rYvPgANIAhVXh8WvkQlioUiFlFcBtAmoiRNdzxqu9p0J7vrdK29zuPeex77nnvO/35n1r1ndHRktI0jTOacv/l7lCBK5UqVpOha/YxmWK7BC4TQFKVXrbYsnimqxuuMVlOQ0XltWjUdCwRJ1M+tC1KudOs9q6+da2adUewG0SC0SwELfHtgDds93VEuydEbl3QMWeNoYkR7b/0x1ZRobGI3mLwzAhePqTAwhg6aogjNsGy7/jwQ4rkdqe7CWLxF8k9LfMVFyRS7VJqtkrW8Vt/bkR8FZJao16ipknbC3Yw2lM7laO6HBEOadEZ2tpf65c4v8e3u7FyU6qbiNNyCuzXZ6pawgnwgmrpTT/Q7w2EZmiIJ0dzWDI7mhQ80IfRnMu2kzA5r5r1pIFoia+/d93HRYp1GV8TbrkWoU/+jdI0Ff6yGwTjT1Hn8J+8m1rKpGiYPuNiHnMtNMIv+zpsk84MYTNW1/+DpwXLvckdOCMYowVNPREe0QlM8xRHXXFhcNDzupwsSmb5pH+0t0RP2Qk+QtI7F1Qm6JRC6ZPBtPq/dq/kH+jxtCljn9TIpW6rQIgmSVyj6lPICIw4N/taka41PFUInth0je9+jO6Kt1G4/a7V2LEgG02B0pHVuCZrgltSKMuIl5SyufUv9mYuQi+mFgzbBEtFo2g+Dh4sSTrLNu8JPh00sQydpb00tqXBvqRN7Q7kqzcnIxCGnvZt/WmJacoOEO6Dcn8Qre03pOCSQxbMOXUuDNx9SxuLz4W1I18gvjViQ67zV0rxdWL8Te/TQkuo8STS41DR48W7L6YP2uWIqiUV8rd6Gbf/rnegKZeG8TpAM6afhGze9JAOxbLjsnUXEbrZ9vLYd7MT32cPF5mKKxmjy7huaoD9n62GOxni3iIJwv0IzZAZjdZkUtolCNLVfYZNaquFjGszVVf+J0vrz4CawoKdHnOzb0NMH7CDBOybfYNJ4rfeMyFNjkFYVTzMFs87rnPGXLUOeNKRVc0LnU7/UIgelzsy3CMuth0YfvnY0wsD3vODUL3eJcKqHQpm8yM3XZQWJxO6Un9iYloyyLpOwN2obHy6W6gbpcb44XmyC+mg+itAcaprGcrwZCqMj/GmtKn0zPvpTz/Cv1dw21XwP3cRupg3H3MF/S71eTKj1YrdwKdc2Mw0fRmb2sFf8lW3aU6JbIZSEPqvXvjM7G/aApyXlXeqKfMq0g/Su3rUGJPSPrtGElgknrZM3xUXqsAP6zMCNVn5u8aJnSNpJv2uru7t2jfRziW2+GuhqfldUNbPk71olwo+46ePUo1U3WKk/e5YK07F/wGRgcpODmQnIlVeHCWBE4puBi2jq28UKpqiN1/4UOrGz59TNYrrQHtd+11sG40BGD+pXdelNqGOg4NXe8W4eacJV/NS9/2Umtym6WQqveqR9xdCMElpxnbkalM4Vf9uaEcWZaKdyibEIjWKxJZPN95niCL3GiaXyssIrHxoLkqkzLCXULN46/f2h3tQJgyip+Tk9EAjJ9aJshq7t8X45aowSKspMSvPf7r9R8yxNptIaHS5ozuEm6luPDApugyNP8OaqiQ4BjaequXA54SLC83eHIY2r+CZp4409Xqw8Aa2oI7XkCrQi+in0w5AqF/kLNrcUz+qkl/lAobY1jSnx5OJNhyXIz3qfNFlXc0TKaglNwdWkWYt9QQ1Kr6W8zue21iNrdJk+N5oCr2O9nEtWKC7IS5J/zdDEYrmnAYfg6agCy+qcgz7ZofeDc4PbUWSvkshWuAc7OjiUyLkj+RAtdlwXJcjxdpkTTHDhK8lBCi8+JtvDVL1W6elmOM++YS0LuSlaP1oUvAeiW3cFnvTr8EbTz1tsSMYdGeZe40sRWu5uAfj7q+ZoKv2FNQ0p5XY1lmlcigHZqTPpabufEVrNuNPi165w3uCVQJHyJqmSJ7ZHnguqwtCmwViIJijj04ba2JNYtB+yORf5gg1/9t9iw4vUpeqiunSAbf+IBdj/b+iG2qrHvuNP0Vd/+ThVZT/lrvHYjjgDbbyxaqgHNM2uhxa1GW3UedZYhMMwM4mQhltouK+IV4NdbIQNM+8Yv311RZk9kT4tiYR4LkyFcuPpdcjuhUuFqBAWRZa11lcZ3gEBlXywsNhrt+plISZP5DlsV9l4EgY6J3yZPTUcMrgaWAT3oI79eSbGEbcJpr6BD8kyDiVt+G0/hXosQN4NFXKlfWIfsIs0BHODVok1/IGnKFHJYIquh8Xo+2+bkQNTGgWmN/fZ0Y33LSj6lr1GyV7mWIKg7ZTRZPGuhF/zjRNcQ1UPtSYgnWQxSs0yrVhwNDcdGMNSNe2JT3WuzbAM3HykyAajS3Uphf6STKEqxLas9EnmnhA/lyj9Uj+JoY7SVgVmGLl46Rm2u98sbkap2lzAdKBG4r6LgulQOSSjQv1GWdQ0jtDUK/mAaqM1Uqjpu4k3Rvfvxv7YTxLSK+wN3E5jVIzmF23uZ7hiH/sVP49D7tvoKp4S8b1LuvRlivVB/algbhcFITYVXvDpLzpDfplR2uD5V4XJFxpjmIpLc9Y5sB2TpBRix7Bme6GZIq+06v3XzNeTcA4obQIKxrnT4C2JpOqD92dbmSX8MGazly5EsZVMvSU1f4RZwyu8iQXbVdeLlZrjuTT1jrY1uk5c7iZ7RsvhhluqAkq4JpVQAg7RJFtSu+xgJ8Pv6O1j5DkLxT8mkbfyRW5DrQmG7hiDIjCgBsADbjuof6YHLGeV6a5Q1Smx9joUXPpdaaDx97A/Wq00oJkdR7ZYuQRfS533JtxO1erduqWOYIt3wh0wpbLuCNIYkwxbswbikCUu2CDCS+Q+7rgVtfRcm+SOcdKPRlZ/rE7wNVUEE39KTS5uvUKN1PUnkloPkyzhyGQ8qkouEjJ3H/VXdqG6asSRiw3ecMlBvDDt8dDhBHXMwZ2Cajzjr7/76T+IavqPYvz6r7//E/3X3+N//h/0QozbjPgPiir69P/8X3/9F/yv8b/827/++98WItPu5/Hvwd8YPf5bp/2/lX/T/+Of/0MJ/lYTa+L/Ef+d9vN/3/2T6P/+jyTzu/evf6U7vxN7B6pJkRtAF6jUr8I+P8RsP/ptGhfqFk+pQ/DgAy6NJtRYJdXmp4gK7WLqLKJ+MaKhGjOojvL+SnIWrkpy0SLHDe4QuyNzaEA15mLMCcmE8Em+4HdOihW4/ZWuppJEmzeAwcDtv7MuLc9y2V5atvxXNe3S4DUMt5/Qy2LM9kSYKiVWBuKlfp4nxTntpuW03JbIlkiRvBXmT23g1I2OYe6IizUHPIq6zm6mbfsbteKmi/sg9J+ocQBMctGFO7iljo8TPN+z3jxw4do+ZwfqoR9dkNTKHyM305GpTkfhcHexVkPVGEbUOjuo9f0UMPHBFlGEx0SLvJvVRKTwW7PSew5oPme+E42+frJa9cGt2njS3dK5kIif2eYbhuSEQXEqMVfUjhGIuin0G0/W5ezJyJQy3SpMLai4M0JUWb5u1k9tny5bd1pPwYBpQuDCXZl62xg4CdVEAtflXHs6JKmP/pH6mOl796Lgopj0o8d5kKh00hxG3OSdEE/QBo9Hgr8JJqAeLDwJohG5j/DGh61Rc/+tf22/8kEnxHNCEjo0ElvvGfESZkqmz2BDcKV1H1buSkhkdg7p1IMGs2s17nYjpblrWuE2K9WEO/hcRp5e9oOF/QBmOaDtgil+oaU6szPrdwW65fOB0KUTsVUn7LFU7J8e6cxJIl9+FHw5MQMzuQJ+4oxMH3iW/5GK+hWuG0T+gTLs+fAjdtUd58TmIUq04EeyRCYCjkldow234aIgR5bqwrtZosZ+6YEqAmDqatJ9lWasz4IquKALPtd92hGI3Z2BdzzZue+REl1Om4DIWD+RrtUTOJLI+S0jHowXXdAxsGLSd40zYNuEUlOGhrwL6c7tcOtUOvpJCP7QBQS19H+GvZn05ewjlVLz+IGKoC9TyfQjLMBNmXCuqqtTdOSukZW48B0HqgSTCBrBnlFvF4CG2Su7yFzqmJFURK3UmTT3ru050r0ptUpMilYnBJWfl2Bv6kPlUuE1kxxpdzui9AubsR2N2boVSu81OulAwBqoSr1LZ0LLYOomyZHmjqnXlP72s8LnDouEJjtodBvdHaG1jMySYO7crWd90MpCRyCG14vb5IE7Arupw/y/RcCm/Tm3zK6zYj8PYNaGldiUfkB/LHWcmf2lVM+mwyU27a0qq2tscrQ/vzBjN26DnntIrOyGizzXK35yKQdYnUABkyN4saz3WD/viF+eCcsXnIajdWYJWaYHRstIis9CS+tqnFGmz2j5uzfr3Z4prqgK4XOT/PyftvjZqIm8lhkfxJ7Ol3CJF1piYBGAG8wtAk56Drw1YwmOpcz+NdfkSpSLplRXLXHL0Rquj6YW/gabqgK7Dgr6NwtH0B/AN7XrN+MVJ6AmXmUuqmQulrNNYPmH0RoDogydOKLo/QbfYNARSQQKISRCzRXU+q9WWJFL3LZW6u34CkeG97xC0NNGaJ0bvK6SnZS3zPskr5EtuCgjMWR5o2x5BqhKmDWJPRe7JMEOyRb5uUKlHaGVtq5ivSOaSliSXp9SQm2qk8MRJh10MAp9QQ2H5t59J8rjiwSZtoIfMGjlLPVNdYl/LBR0AO6WLGDmkLkIPRE45Y9MftdAK/yNu1Hn6tzOQTesgQ+8fSzB19wO91vCnO23vOWQdwJ63SJrYjdfKFW6W281PKs2k8iT9ai1cgJ4sa3xqdvmtxR8/+D1B8AKc2u+6JftryRhMWSQtoSBgIyyQGyxcnELuAasXN12oSriU4RMz1DD6RL0TSV+om7i1Yt+jEE/jnawM8cX/UhN4nkiv/w9eALrzNhXuQfOzFL0Fi6SjF7/4Qn8rLYBoa85cvgAnkCEBP+HPbEnquVXCZsMS/yzYw2Vru60P/+nJPYKkzZFjmbykzUoEqV836T5q3fP/L383dF82tx18/AZgZczMAgyeWYKmSZIqtHL+e+O4ZRcq9VI3g/qPeCoiK4pcgEqdbS0S/Be54sbVQOuJVPNBblIghzeasNu7h/g+Sz1IdhI5lCwq1nUb3Ji4OCIcqQZqtqJ5w7rXrg/DA9IgVmEGhDgGecEwnCTHffXcXs0V3OCEVzYDKS1vp/oX+ng+6XVU86UjA6FMO2RXOOOrqY1GgPvrAk9HV/BXtCu5RuwF8qgdGDLsBcui4E33ymdBip1X8uKyhIWT8qNRDsXz+gvO9UiEC0d8RG4Tf2x8H4slljgHtCBcxHLTWOYJm5H/fCPCzOgf9qgOUxTRZ0Pc6ha5yLuLVT9ntvIa6gacE99mCovdUumTQdRP4RPsS9129eEe2uSvvGh0bV4Y3QPPhPZMqhZWSMa5R0Hc1SGO4IVOQc0FrirlibTVfKRrYkD8kz3b+X65/QkUNaZdrdl3mCap0Hf3YcCw/LiouJYNbqz88UqeDYv93yO7vvXtgl4XCyAO4ODkY6W+83+LZU//p3/zXNGGrUKClCiOnL27iJZbNWDF02XXAOeFlB7IaADoMH1Yqr+UP9biyZDEa/iJt4MDeIz6GKTdLVBfWGVtRN4fdT2rgReX8UXwF2zOrradm4J0nyTgdPnai3RvzpZvCKDUqjOwD/QA6EDaMCLewX6QWYVnHY1sx1bd8ovYnPm1ZvPH+rE20lWjOCnZ66/xDt0QAl15FjfBcZp+i9OU0RNPQ0t3x2pSNWo8eiYudwsnuP1Hq6iH1LJCJynkYsfgJ0p3pF6SoQk2l+jqE8CPk+ziGJRSKjs+W5AO185umPdkYzlK4wl7TC9NxyyDP7ZoyYVoXiuS6SjnInlLWrwz1i8bGTKXX0AVQWkSfIlglW3zRJRJ8bg5VgE6ZEnqNu9B++0GNQvDQJvFize4ESNKBJP+8vA3LM4AX5SIBq08Mob+7QMTCZx4nwP/64+4BnlZC+8WtlP/CXw6t1PwMwkJ3jhP1FiXLhDF/3I6FGUzO2DSi9ABxKyyL9paZxSEz40ZCPQToDAJu1959k7QdbVxgB4icsu2s4zsTPJhcEDo+N1GX4zSk/wriRh8AqwL62972i9HJHd1ydaLXVzvKvOfGGw5RVcUVMiKXFH4APdkQU/dc5BX0YfKTNZYXCW9mb8bc8mufoQP6BbdQmT99ZjoYfr/go4TgQX9IDgztim7wyFeGMfbNaeqj8Dzs38pgcqwSv2hbqB3oSGKWKy+sesY7p57wAHldqE6NDudk/W7s/zjrK4rZFlFvaGxnSZdHbc1y47qDN6xkoK8O3bfr2j41dlJZ71rB4dlDqapPFa8N6xBrprUdtenUCHwxKNhw1uuTBh+9uU45k4REpQABN2bAO9DSLqoIL26gNroWgup5pUMxHUNSq4Gyz47vBPvilpo5f9OYI2ddAqTqmnxXERxQJ3UK8fHbVE9HagHi3+tqNRoNsArdmAxHA5LwtQo9ZAaNKUTljnokljo2x8scqVpEEIPc01fPCdHOCg0DeWBz8D5TVAAfx8aRH5X2ZYNI3ebKDZdeJ+oBDAxmRqJ30Eh2/DaeAy5diVNMpEDmXiPDsGTzBLXy8eVDdJoIafgx/gxMyQi454QrW56nCyeELgSuNNEmYkflF+t3CZQOVRWjKhIuCclmQSlAXT3+4JGG75B4t/5hQ+ldMP4LsAW6z3XmU6IJJwpnGVnsgUZhoY1fZlwTR8wSU7xRejf2uCx9Z5trVTRRJP9KnEb134dEieil6eCOGWgboI7xsqsqM99jfJLTePjygKlH2CVxxsse9QRzTBFjD/Kjqitr/CCTBt/SJ6nLxz7cKP9pFqBpp0lN5y+adKNsZjrPuroemZauH9aTTFD3EKHW8S55XBLFQAt1jgxTQCTwxmx/JyfsZDN1RroN3VaxpSenpIX7K+ZbL8VdlQDcI4Cbzg3QJLa9yVqNxUelu+EtxLVqeekaAvSJkO6sSVqbUajxqhKshNpvZqoeApF0k/0P0ikkwUcbdwc4A1ejN7Oo0O15kG7hTMoK3hZRBCX7YYeLW0wvcXx/18n/u37yLgzBYVBUvORGli+sfRcX/74uD6P4hq+7xu54TlWJLFzT63uwUDwuEDdOjJQqx7JV+ZjaEAPi7t0MMrR4Q8Rkf18uxD6RK0RKh0hL8YU+DeL97i4pa5ZSyAfXKwZRS/8gXcxdZXm62RBDj8U3sN8x95b5PpPs/mCBKYvpaA50pN5Ct/499AFTtwQ5vgeSh+NHrKIi4NVpwM/XzRaNfJD856lPE6M21zWPguFsH7jbLVyEDfRmt4VwrhCJ5VTYmcSPfGgO5clfN+vbaDZ7sakU5+2vZ2WCDY031NxJarVytfDDVtiafcTGO2rJ/taoL3zChN2qmjxofczTOYQPPVQPh0JVtYgdUQINcSiNEEy58UdYXX1MpWUCEBx7LbcGtAm8XWRQTVOaoV3ySri4RShhs/B/0m4jX6OAwXOvcA09bNSG4czEGv/Wey6V/jbTCNTW6awXdNTcA1GsPe1E9fZdGl7R0vyoVpIdJtfC6d32NNErrvq/R+d65VG+YOwRXppXxOCYyGNSf1K3x6VxAW/vtz4EC1SgCOSPdN62sLsoIzuDfg8GwZAbquVO8HIuFP/ToVoeUB7nnwMF35a1wK1tI6fkrqFKhQdeJpwyls0pIy8AZde3/6LUUbFaYJthyUJSU/kqDXTLQElnn0Jr4B2RVghNrmNmoEn7pXIeshPguXVsvwoTdmClq49JJU3LWhHyWTrJL9bRP6VKv3tZoA/th77p5Jw++OEENvyvWy/pNeExiDUVQaXIRGh8xySZTI36yueFaSXo1uJY0RnXYgEOoWWOJHeaVuX/bGNhHsh2yinznl/++NJcE9j6fBPRcBdq9hb8awNw8U7Bl6GM7x69EDOIIbX/npZ++amlHR9L/35mE/2Ss4gb0xCcY4VyTFLRE796vHysLAamqcyO+aFQyJIDBNslbH2/MrAvZiSEIedc/cqjmv4fbda2pXbv+F5a2szSsdkm9noiNURXt8edUhGUF6fSZWd1IJaXKFwD+49R6eCXD4Bkef7j9tRtNMVgW8BhRz/Qpy1TmeYk0doyjZoJSbePOReVHgkFsCFuQJ+Lgc4BxeAsK/cOiNDRmdNw0ctYhn/nQ498dYI5znzGLoJi1rav7Cn88rL3wLePVtDK5gl77Tki3gHEsIAQ2+IKgarj7Y8W1IQzV5V9N+0TjLqbg68WfKcOmBCOj3JkwJhVIkwDhc+JorXuZEPMEh0vvH3x7iqf+VAwXgd4diZiaJD1zHL9Snx6Wfg4IugreyhabQkcir+y5XgDtdx3Avs7lkeeCBwDvZoTUCXx5QrZkcEqWfYEiEYRs/EphmRALSNGR1Iclgdr5VFoELpzF4++f35w3/j0t5ucW3n2ch4PQCLuUXupsPRR7UA5FjSKrMtPcKAZJfagO4lGE7FH3YKMjorpK0ZxAv+i2JkJhtAMWWWFej4RhPR/cJ3DxwocCvXDi4SGZU4cu+K32XndiFWgopAl+0GApcwf1XvymJcFs39jExIBO4yUjU9MExBLQYc9H+W7+IgdESPRpciT+rKZPebVtaVq+1GYO/5xTAL3HASjNTGIgMvdjWbgc7JvdE1zIFpuC0U9ESiZyzBixzxWxj4Kwh8My34q+FK3KNLtmsA1qyrmKSNQOXCPUZd+ONelBTvFoUI/CYsqa/RhtKiyMf2CgSFqEPk59Y3uqnlZ8gFpswfSYyko23yVZYxzKGxGm49Zqxg1l8oz5Ra9XaRwHkuxepmgyhm0SoNy2KlbcEqK+9QqS9PNx9Ihm9U7gsR55SSJ1FBDNnkuWKxIZ0SDpXuOGwZdoUbOMDPHP4vBAgz2VlSEJAHZGJVbYIg7l/FO5KfIVvxC8pPPxMGcNMoevFDeStt2iqztE10n2TA4dgJH76YS9HDhKHD3iCx6ieFX84BAI3QQnngh76f5ruPQVbr5qZmck/5UjDc26lfrOvUBWy0Ogl8bCoOkMOns81TnC3cuUS9KW8+9A+fe3XYZOFUPG1u5epSSmDLw0s5s2F0W30ANeo+zJkJQz9SPZgzwYpEoktofhGVfmLOAB20boCbW1QWq/NpET/hnMecw/uSyAH4NJc3ECOU4nnkK1fj3S/i5dwb3R7k00AqQQUwt7Ie1qV0aY/VQX0J8hLPy7eBNXMHYZYDNxHZ2Qh6AuXJxq+AeRec/Q+JLhZV6hpXwQEzw7bf5v9uUf2vpq3qlhmy0IIGTkwYdCfSAFmqbdo+3XvDTDjFJde0mbeQLcn2n31xaAqJ0ixO/CLsT4I4G4DoncVTgRGNBtsCcjISWT+oeXZ4Iedw/8OsJI1aPnNKLX/60VvcZb94uasRxCkqlPQ11u1Sa2hHvB80WQENxVyzjns0/PiEByyil21Te6oisk3mNCEMrhouCFO3yEZTHHOCMy9eb/4Tmi8cVf3Lf7P53SY2hX3PSN033As3ETIMLHWumWEO9JXHA2y2SIBlIPpLGG2qvNsCIlIr+B1SWAqRKm2w6Blf7U+zCSBwJrfHG5i8J5Gax/cVonMlon7aHJX/gSvucIncRP93XCqkv7D8IFKFsLiBgHqUpXhE3pYjEcV1dk/JD9zFVCfEaQIVX8Jmfz7IIofcBKQ4OaG+C3xC2veX9CD+iAFXDNaGg9eTVxvkbJRJlW4Nk9Wk13kn696jWppRDe/8pDrYMO9ZyxZ98ReKSz9kWKLLyk2zCZgAniCkLJVX3n1M9DYbomyahWiv/KixRIV9hj/oFz87I+HLznbPTjpa+D+bZQnMuRsljTpv90vQUt/pK7jCFnA30B/jtroSF2/m/gpWn1aQs5WeA6ghzF8SdqWI20fghdSeDOCSCmLgTkfaGgGDmw7nHFkRzGtag57IHS2na06I+gzEphXo1w/Zx2BM/jKL2nZoFjHggtFQjYi8nSVRSXIE58RPbBObXk7uuIL9+rs/5Zo7suJInEUxgsiZZAWS25iBtpEiZeBgDtghEoAE0sjcayNq85M4tbu/LF5h51335PsGzQ09O875+vUS89lkWMyNOFoip2PuyWyMP/iU2XIZdfCCJNDjebDoBLQdpy7QQZC7s9c0wjHJervQNDu2jWzBW5MSAJMr7bP+Iv92BkS/GGgzjEn7MF1IRKFwwzbjbS4/slGOmhx9cZrFu7HSEefojNv3r0UaKfKOWzXsq1zEugbzlMDFsacRJJI/iJlK3vtkZ+PLZIVMFlKA32wbq2Kd5T0uCLZ1CPkAfCdzkz2EYscjDcZq2AWfziN2covN4kXE1lQXPPLTNM1xx3tbiepcO/t3SWm4w87qfh99SL0ZnY+LKFPLPeXVM2mIIoVWt+9Nk0I7nY4O79iGYqxZ8RVz289an6NVdJWnSKZvJQCAuHNiVaDxPAFoH392t9wot5t0/qmU95eEWNbU2udUW5sN9JVqcYlvAIfLeYC33oUzzxZgSktsv21mA7Uly1FA5VnoJFh6N244Wmv3YJGFv/TCPryaw+ZORlpZjQdq/2DYXr3EZskfed0G61P09ipTKmlTQ1067Rg5+PAk5FlQ9e0SWbGf2B/08kqymOTMVOznsALHHNFH4LFRKl2F/NOiYFl9khNHnSu9Ak5sq26Ynl/i2fdTle29Y1ugqmR5Yj4YT9pvslFyYCbw0mNFr5rVQm1LvkG27QMq9ph3t8fmn6r6SQ4oSbr5tz+J1kIawGzDxb6VYOvvWhobDTXfBeNv3b4aNm5XUinsCGqG2q/45m3+LoCOsddFceYhRx1Tsss9PLdPfJdErFMjYd3gddjiP0+XQjcRadZP6bwNLySvunFf20Czy6JqdEW2a96KxdYdOryBv1BjbuUq2yCHeh+6sk7fGmmPi50pe/1l5TyPe5oHW9oPnhPswLyf2TFDdCyYlhwBCstv5C1HwlW7xWoGT9XZt4qVj5WryLPLLD6h/5cMLEjWzgCeAIKNsLak92aBqBsHl4AJwl2N4jfvbSkBExGimv0nFvv09uDScQbjx+w4kPQjgjlW+g9ws9VEJvI2k8N6XxVu0uIwovgTFdunG24gBtaDi+y1YLQwZ8mwbip5fVlO3k0n0AEr/ETbtu8Vjkm+nNSiEb7X/3fMjBL5A8PdgG+/FnbexbFFExmEfetXAnisEKy5z44WVPpQZjSy/jzeGn4yDRsFGqhh87QPaDBWhlo37IFbe/C0xynS91d2tP/AJoJS0sVF6iwAAAAAElFTkSuQmCC");
+}
+
+#menu::after {
+ display: block;
+ content: '';
+ padding-top: 80px;
+}
+
+#logo {
+ position: fixed;
+ bottom: 10px;
+ right: 10px;
+ background: rgba(255,255,255,.1);
+ font-size: 11px;
+ display: block;
+ width: 20px;
+ height: 20px;
+ line-height: 20px;
+ text-align: center;
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
+ -moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
+ color: inherit;
+}
+
+#menu li a {
+ display: block;
+ color: white;
+ padding: 0 35px 0 25px;
+ -webkit-transition: background 300ms;
+ -moz-transition: background 300ms;
+}
+
+#menu li {
+ position: relative;
+ list-style: none;
+}
+
+#menu a:hover,
+#menu a.active {
+ text-decoration: none;
+ background: rgba(255,255,255,.1);
+}
+
+#menu li:hover .cov {
+ opacity: 1;
+}
+
+#menu li .dirname {
+ opacity: .60;
+ padding-right: 2px;
+}
+
+#menu li .basename {
+ opacity: 1;
+}
+
+#menu .cov {
+ background: rgba(0,0,0,.4);
+ position: absolute;
+ top: 0;
+ right: 8px;
+ font-size: 9px;
+ opacity: .6;
+ text-align: left;
+ width: 17px;
+ -webkit-border-radius: 10px;
+ -moz-border-radius: 10px;
+ padding: 2px 3px;
+ text-align: center;
+}
+
+#stats:nth-child(2n) {
+ display: inline-block;
+ margin-top: 15px;
+ border: 1px solid #eee;
+ padding: 10px;
+ -webkit-box-shadow: inset 0 0 2px #eee;
+ -moz-box-shadow: inset 0 0 2px #eee;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+}
+
+#stats div {
+ float: left;
+ padding: 0 5px;
+}
+
+#stats::after {
+ display: block;
+ content: '';
+ clear: both;
+}
+
+#stats .sloc::after {
+ content: ' SLOC';
+ color: #b6b6b6;
+}
+
+#stats .percentage::after {
+ content: ' coverage';
+ color: #b6b6b6;
+}
+
+#stats .hits,
+#stats .misses {
+ display: none;
+}
+
+.high {
+ color: #00d4b4;
+}
+.medium {
+ color: #e87d0d;
+}
+.low {
+ color: #d4081a;
+}
+.terrible {
+ color: #d4081a;
+ font-weight: bold;
+}
+
+table {
+ width: 80%;
+ margin-top: 10px;
+ border-collapse: collapse;
+ border: 1px solid #cbcbcb;
+ color: #363636;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+}
+
+table thead {
+ display: none;
+}
+
+table td.line,
+table td.hits {
+ width: 20px;
+ background: #eaeaea;
+ text-align: center;
+ font-size: 11px;
+ padding: 0 10px;
+ color: #949494;
+}
+
+table td.hits {
+ width: 10px;
+ padding: 2px 5px;
+ color: rgba(0,0,0,.2);
+ background: #f0f0f0;
+}
+
+tr.miss td.line,
+tr.miss td.hits {
+ background: #e6c3c7;
+}
+
+tr.miss td {
+ background: #f8d5d8;
+}
+
+td.source {
+ padding-left: 15px;
+ line-height: 15px;
+ white-space: pre;
+ font: 12px monaco, monospace;
+}
+
+code .comment { color: #ddd }
+code .init { color: #2F6FAD }
+code .string { color: #5890AD }
+code .keyword { color: #8A6343 }
+code .number { color: #2F6FAD }
+</style></head><body><div id="coverage"><h1 id="overview">Coverage</h1><div id="menu"><li><a href="#overview">overview</a></li><li><span class="cov high">95</span><a href="#webidl2.js"><span class="basename">webidl2.js</span></a></li><a id="logo" href="http://visionmedia.github.com/mocha/">m</a></div><div id="stats" class="high"><div class="percentage">95%</div><div class="sloc">572</div><div class="hits">548</div><div class="misses">24</div></div><div id="files"><div class="file"><h2 id="webidl2.js">webidl2.js</h2><div id="stats" class="high"><div class="percentage">95%</div><div class="sloc">572</div><div class="hits">548</div><div class="misses">24</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">3</td><td class="hits">1</td><td class="source"><span class="k">(</span><span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">4</td><td class="hits">1</td><td class="source"> <span class="k">var</span> tokenise <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">5</td><td class="hits">47</td><td class="source"> <span class="k">var</span> tokens <span class="k">=</span> <span class="k">[]</span></td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> <span class="k">,</span> re <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> <span class="s">"float"</span><span class="k">:</span> <span class="s">/^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/</span></td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"integer"</span><span class="k">:</span> <span class="s">/^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/</span></td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"identifier"</span><span class="k">:</span> <span class="s">/^[A-Z_a-z][0-9A-Z_a-z]*/</span></td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"string"</span><span class="k">:</span> <span class="s">/^"[^"]*"/</span></td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"whitespace"</span><span class="k">:</span> <span class="s">/^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/</span></td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"other"</span><span class="k">:</span> <span class="s">/^[^\t\n\r 0-9A-Z_a-z]/</span></td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> <span class="k">,</span> types <span class="k">=</span> <span class="k">[]</span></td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr class="hit"> <td class="line">16</td><td class="hits">329</td><td class="source"> <span class="k">for</span> <span class="k">(</span><span class="k">var</span> k <span class="k">in</span> re<span class="k">)</span> types<span class="k">.</span>push<span class="k">(</span>k<span class="k">);</span></td></tr><tr class="hit"> <td class="line">17</td><td class="hits">47</td><td class="source"> <span class="k">while</span> <span class="k">(</span>str<span class="k">.</span>length <span class="k">></span> <span class="s">0</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">18</td><td class="hits">2914</td><td class="source"> <span class="k">var</span> matched <span class="k">=</span> <span class="k">false</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">19</td><td class="hits">2914</td><td class="source"> <span class="k">for</span> <span class="k">(</span><span class="k">var</span> i <span class="k">=</span> <span class="s">0</span><span class="k">,</span> n <span class="k">=</span> types<span class="k">.</span>length<span class="k">;</span> i <span class="k"><</span> n<span class="k">;</span> i<span class="k">++)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">20</td><td class="hits">13325</td><td class="source"> <span class="k">var</span> type <span class="k">=</span> types<span class="k">[</span>i<span class="k">];</span></td></tr><tr class="hit"> <td class="line">21</td><td class="hits">13325</td><td class="source"> str <span class="k">=</span> str<span class="k">.</span>replace<span class="k">(</span>re<span class="k">[</span>type<span class="k">],</span> <span class="k">function</span> <span class="k">(</span>tok<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">22</td><td class="hits">2914</td><td class="source"> tokens<span class="k">.</span>push<span class="k">(</span><span class="k">{</span> type<span class="k">:</span> type<span class="k">,</span> value<span class="k">:</span> tok <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">23</td><td class="hits">2914</td><td class="source"> matched <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">24</td><td class="hits">2914</td><td class="source"> <span class="k">return</span> <span class="s">""</span><span class="k">;</span></td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">26</td><td class="hits">16239</td><td class="source"> <span class="k">if</span> <span class="k">(</span>matched<span class="k">)</span> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">28</td><td class="hits">5828</td><td class="source"> <span class="k">if</span> <span class="k">(</span>matched<span class="k">)</span> <span class="k">continue</span><span class="k">;</span></td></tr><tr class="miss"> <td class="line">29</td><td class="hits">0</td><td class="source"> <span class="k">throw</span> <span class="k">new</span> Error<span class="k">(</span><span class="s">"Token stream not progressing"</span><span class="k">);</span></td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">31</td><td class="hits">47</td><td class="source"> <span class="k">return</span> tokens<span class="k">;</span></td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">34</td><td class="hits">1</td><td class="source"> <span class="k">var</span> parse <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>tokens<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">35</td><td class="hits">47</td><td class="source"> <span class="k">var</span> line <span class="k">=</span> <span class="s">1</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">36</td><td class="hits">47</td><td class="source"> tokens <span class="k">=</span> tokens<span class="k">.</span>slice<span class="k">();</span></td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">38</td><td class="hits">47</td><td class="source"> <span class="k">var</span> FLOAT <span class="k">=</span> <span class="s">"float"</span></td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> <span class="k">,</span> INT <span class="k">=</span> <span class="s">"integer"</span></td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> <span class="k">,</span> ID <span class="k">=</span> <span class="s">"identifier"</span></td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> <span class="k">,</span> STR <span class="k">=</span> <span class="s">"string"</span></td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> <span class="k">,</span> OTHER <span class="k">=</span> <span class="s">"other"</span></td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">45</td><td class="hits">47</td><td class="source"> <span class="k">var</span> WebIDLParseError <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">,</span> line<span class="k">,</span> input<span class="k">,</span> tokens<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">46</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>message <span class="k">=</span> str<span class="k">;</span></td></tr><tr class="miss"> <td class="line">47</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>line <span class="k">=</span> line<span class="k">;</span></td></tr><tr class="miss"> <td class="line">48</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>input <span class="k">=</span> input<span class="k">;</span></td></tr><tr class="miss"> <td class="line">49</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>tokens <span class="k">=</span> tokens<span class="k">;</span></td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">51</td><td class="hits">47</td><td class="source"> WebIDLParseError<span class="k">.</span>prototype<span class="k">.</span>toString <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">52</td><td class="hits">0</td><td class="source"> <span class="k">return</span> <span class="k">this</span><span class="k">.</span>message <span class="k">+</span> <span class="s">", line "</span> <span class="k">+</span> <span class="k">this</span><span class="k">.</span>line <span class="k">+</span> <span class="s">" (tokens: '"</span> <span class="k">+</span> <span class="k">this</span><span class="k">.</span>input <span class="k">+</span> <span class="s">"')</span><span class="t">\n</span><span class="s">"</span> <span class="k">+</span></td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> JSON<span class="k">.</span>stringify<span class="k">(</span><span class="k">this</span><span class="k">.</span>tokens<span class="k">,</span> <span class="k">null</span><span class="k">,</span> <span class="s">4</span><span class="k">);</span></td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">56</td><td class="hits">47</td><td class="source"> <span class="k">var</span> error <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">57</td><td class="hits">0</td><td class="source"> <span class="k">var</span> tok <span class="k">=</span> <span class="s">""</span><span class="k">,</span> numTokens <span class="k">=</span> <span class="s">0</span><span class="k">,</span> maxTokens <span class="k">=</span> <span class="s">5</span><span class="k">;</span></td></tr><tr class="miss"> <td class="line">58</td><td class="hits">0</td><td class="source"> <span class="k">while</span> <span class="k">(</span>numTokens <span class="k"><</span> maxTokens <span class="k">&amp;&amp;</span> tokens<span class="k">.</span>length <span class="k">></span> numTokens<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">59</td><td class="hits">0</td><td class="source"> tok <span class="k">+=</span> tokens<span class="k">[</span>numTokens<span class="k">].</span>value<span class="k">;</span></td></tr><tr class="miss"> <td class="line">60</td><td class="hits">0</td><td class="source"> numTokens<span class="k">++;</span></td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="miss"> <td class="line">62</td><td class="hits">0</td><td class="source"> <span class="k">throw</span> <span class="k">new</span> WebIDLParseError<span class="k">(</span>str<span class="k">,</span> line<span class="k">,</span> tok<span class="k">,</span> tokens<span class="k">.</span>slice<span class="k">(</span><span class="s">0</span><span class="k">,</span> <span class="s">5</span><span class="k">));</span></td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">65</td><td class="hits">47</td><td class="source"> <span class="k">var</span> last_token <span class="k">=</span> <span class="k">null</span><span class="k">;</span></td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">67</td><td class="hits">47</td><td class="source"> <span class="k">var</span> consume <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>type<span class="k">,</span> value<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">68</td><td class="hits">8778</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>tokens<span class="k">.</span>length <span class="k">||</span> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>type <span class="k">!==</span> type<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">69</td><td class="hits">5470</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> value <span class="k">===</span> <span class="s">"undefined"</span> <span class="k">||</span> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>value <span class="k">===</span> value<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">70</td><td class="hits">1738</td><td class="source"> last_token <span class="k">=</span> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">71</td><td class="hits">1738</td><td class="source"> <span class="k">return</span> last_token<span class="k">;</span></td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">75</td><td class="hits">47</td><td class="source"> <span class="k">var</span> ws <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">76</td><td class="hits">6961</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>tokens<span class="k">.</span>length<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> <span class="c">// console.log("tokens.length", tokens.length, tokens[0]);</span></td></tr><tr class="hit"> <td class="line">78</td><td class="hits">6115</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"whitespace"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">79</td><td class="hits">1172</td><td class="source"> <span class="k">var</span> t <span class="k">=</span> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">80</td><td class="hits">2294</td><td class="source"> t<span class="k">.</span>value<span class="k">.</span>replace<span class="k">(</span><span class="s">/\n/g</span><span class="k">,</span> <span class="k">function</span> <span class="k">(</span>m<span class="k">)</span> <span class="k">{</span> line<span class="k">++;</span> <span class="k">return</span> m<span class="k">;</span> <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">81</td><td class="hits">1172</td><td class="source"> <span class="k">return</span> t<span class="k">;</span></td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">85</td><td class="hits">47</td><td class="source"> <span class="k">var</span> all_ws <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">86</td><td class="hits">5366</td><td class="source"> <span class="k">var</span> t <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"whitespace"</span><span class="k">,</span> value<span class="k">:</span> <span class="s">""</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">87</td><td class="hits">5366</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">88</td><td class="hits">6538</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">89</td><td class="hits">11904</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>w<span class="k">)</span> <span class="k">break</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">90</td><td class="hits">1172</td><td class="source"> t<span class="k">.</span>value <span class="k">+=</span> w<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">92</td><td class="hits">6538</td><td class="source"> <span class="k">if</span> <span class="k">(</span>t<span class="k">.</span>value<span class="k">.</span>length <span class="k">></span> <span class="s">0</span><span class="k">)</span> <span class="k">return</span> t<span class="k">;</span></td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">95</td><td class="hits">47</td><td class="source"> <span class="k">var</span> integer_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">96</td><td class="hits">273</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="s">""</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">97</td><td class="hits">273</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">98</td><td class="hits">312</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"unsigned"</span><span class="k">))</span> ret <span class="k">=</span> <span class="s">"unsigned "</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">99</td><td class="hits">273</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">100</td><td class="hits">287</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"short"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">"short"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">101</td><td class="hits">259</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"long"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">102</td><td class="hits">41</td><td class="source"> ret <span class="k">+=</span> <span class="s">"long"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">103</td><td class="hits">41</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">104</td><td class="hits">43</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"long"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">" long"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">105</td><td class="hits">39</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">107</td><td class="hits">218</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">)</span> error<span class="k">(</span><span class="s">"Failed to parse integer type"</span><span class="k">);</span></td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">110</td><td class="hits">47</td><td class="source"> <span class="k">var</span> float_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">111</td><td class="hits">218</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="s">""</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">112</td><td class="hits">218</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">113</td><td class="hits">222</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"unrestricted"</span><span class="k">))</span> ret <span class="k">=</span> <span class="s">"unrestricted "</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">114</td><td class="hits">218</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">115</td><td class="hits">257</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"float"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">"float"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">116</td><td class="hits">182</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"double"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">"double"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">117</td><td class="hits">176</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">)</span> error<span class="k">(</span><span class="s">"Failed to parse float type"</span><span class="k">);</span></td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">120</td><td class="hits">47</td><td class="source"> <span class="k">var</span> primitive_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">121</td><td class="hits">273</td><td class="source"> <span class="k">var</span> num_type <span class="k">=</span> integer_type<span class="k">()</span> <span class="k">||</span> float_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">122</td><td class="hits">370</td><td class="source"> <span class="k">if</span> <span class="k">(</span>num_type<span class="k">)</span> <span class="k">return</span> num_type<span class="k">;</span></td></tr><tr class="hit"> <td class="line">123</td><td class="hits">176</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">124</td><td class="hits">186</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"boolean"</span><span class="k">))</span> <span class="k">return</span> <span class="s">"boolean"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">125</td><td class="hits">167</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"byte"</span><span class="k">))</span> <span class="k">return</span> <span class="s">"byte"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">126</td><td class="hits">168</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"octet"</span><span class="k">))</span> <span class="k">return</span> <span class="s">"octet"</span><span class="k">;</span></td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">129</td><td class="hits">47</td><td class="source"> <span class="k">var</span> const_value <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">130</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"true"</span><span class="k">))</span> <span class="k">return</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">131</td><td class="hits">19</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"false"</span><span class="k">))</span> <span class="k">return</span> <span class="k">false</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">132</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"null"</span><span class="k">))</span> <span class="k">return</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">133</td><td class="hits">14</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"Infinity"</span><span class="k">))</span> <span class="k">return</span> Infinity<span class="k">;</span></td></tr><tr class="hit"> <td class="line">134</td><td class="hits">13</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"NaN"</span><span class="k">))</span> <span class="k">return</span> NaN<span class="k">;</span></td></tr><tr class="hit"> <td class="line">135</td><td class="hits">11</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> consume<span class="k">(</span>FLOAT<span class="k">)</span> <span class="k">||</span> consume<span class="k">(</span>INT<span class="k">);</span></td></tr><tr class="hit"> <td class="line">136</td><td class="hits">19</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">)</span> <span class="k">return</span> <span class="s">1</span> <span class="k">*</span> ret<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">137</td><td class="hits">3</td><td class="source"> <span class="k">var</span> tok <span class="k">=</span> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"-"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">138</td><td class="hits">3</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tok<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">139</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"Infinity"</span><span class="k">))</span> <span class="k">return</span> <span class="k">-</span>Infinity<span class="k">;</span></td></tr><tr class="miss"> <td class="line">140</td><td class="hits">0</td><td class="source"> <span class="k">else</span> tokens<span class="k">.</span>unshift<span class="k">(</span>tok<span class="k">);</span></td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">143</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">144</td><td class="hits">47</td><td class="source"> <span class="k">var</span> type_suffix <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>obj<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">145</td><td class="hits">249</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">146</td><td class="hits">263</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">147</td><td class="hits">263</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"?"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">148</td><td class="hits">11</td><td class="source"> <span class="k">if</span> <span class="k">(</span>obj<span class="k">.</span>nullable<span class="k">)</span> error<span class="k">(</span><span class="s">"Can't nullable more than once"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">149</td><td class="hits">11</td><td class="source"> obj<span class="k">.</span>nullable <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">151</td><td class="hits">252</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"["</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">152</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">153</td><td class="hits">3</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"]"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated array type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">154</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>obj<span class="k">.</span>array<span class="k">)</span> obj<span class="k">.</span>array <span class="k">=</span> <span class="s">1</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">155</td><td class="hits">1</td><td class="source"> <span class="k">else</span> obj<span class="k">.</span>array<span class="k">++;</span></td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">157</td><td class="hits">249</td><td class="source"> <span class="k">else</span> <span class="k">return</span><span class="k">;</span></td></tr><tr><td class="line">158</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">160</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">161</td><td class="hits">47</td><td class="source"> <span class="k">var</span> single_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">162</td><td class="hits">261</td><td class="source"> <span class="k">var</span> prim <span class="k">=</span> primitive_type<span class="k">()</span></td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> <span class="k">,</span> ret <span class="k">=</span> <span class="k">{</span> sequence<span class="k">:</span> <span class="k">false</span><span class="k">,</span> nullable<span class="k">:</span> <span class="k">false</span><span class="k">,</span> array<span class="k">:</span> <span class="k">false</span><span class="k">,</span> union<span class="k">:</span> <span class="k">false</span> <span class="k">}</span></td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr class="hit"> <td class="line">165</td><td class="hits">261</td><td class="source"> <span class="k">if</span> <span class="k">(</span>prim<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">166</td><td class="hits">99</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> prim<span class="k">;</span></td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">168</td><td class="hits">162</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"sequence"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">169</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">170</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"<"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">171</td><td class="hits">0</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> <span class="s">"sequence"</span><span class="k">;</span></td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">174</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>sequence <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">175</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Error parsing sequence type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">176</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">177</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">">"</span><span class="k">))</span> error<span class="k">(</span><span class="s">"Unterminated sequence"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">178</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">179</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"?"</span><span class="k">))</span> ret<span class="k">.</span>nullable <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">180</td><td class="hits">4</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">181</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">183</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">184</td><td class="hits">158</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">185</td><td class="hits">169</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>name<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">186</td><td class="hits">147</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">188</td><td class="hits">246</td><td class="source"> type_suffix<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">189</td><td class="hits">246</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>nullable <span class="k">&amp;&amp;</span> ret<span class="k">.</span>idlType <span class="k">===</span> <span class="s">"any"</span><span class="k">)</span> error<span class="k">(</span><span class="s">"Type any cannot be made nullable"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">190</td><td class="hits">246</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">191</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">193</td><td class="hits">47</td><td class="source"> <span class="k">var</span> union_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">194</td><td class="hits">11</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">195</td><td class="hits">19</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">196</td><td class="hits">3</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> sequence<span class="k">:</span> <span class="k">false</span><span class="k">,</span> nullable<span class="k">:</span> <span class="k">false</span><span class="k">,</span> array<span class="k">:</span> <span class="k">false</span><span class="k">,</span> union<span class="k">:</span> <span class="k">true</span><span class="k">,</span> idlType<span class="k">:</span> <span class="k">[]</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">197</td><td class="hits">3</td><td class="source"> <span class="k">var</span> fst <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Union type with no content"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">198</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>idlType<span class="k">.</span>push<span class="k">(</span>fst<span class="k">);</span></td></tr><tr class="hit"> <td class="line">199</td><td class="hits">3</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">200</td><td class="hits">7</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">201</td><td class="hits">10</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"or"</span><span class="k">))</span> <span class="k">break</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">202</td><td class="hits">4</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type after 'or' in union type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">203</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>idlType<span class="k">.</span>push<span class="k">(</span>typ<span class="k">);</span></td></tr><tr><td class="line">204</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">205</td><td class="hits">3</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">))</span> error<span class="k">(</span><span class="s">"Unterminated union type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">206</td><td class="hits">3</td><td class="source"> type_suffix<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">207</td><td class="hits">3</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">210</td><td class="hits">47</td><td class="source"> <span class="k">var</span> type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">211</td><td class="hits">261</td><td class="source"> <span class="k">return</span> single_type<span class="k">()</span> <span class="k">||</span> union_type<span class="k">();</span></td></tr><tr><td class="line">212</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">213</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">214</td><td class="hits">47</td><td class="source"> <span class="k">var</span> argument <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">215</td><td class="hits">79</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> optional<span class="k">:</span> <span class="k">false</span><span class="k">,</span> variadic<span class="k">:</span> <span class="k">false</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">216</td><td class="hits">79</td><td class="source"> ret<span class="k">.</span>extAttrs <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">217</td><td class="hits">79</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">218</td><td class="hits">79</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"optional"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">219</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>optional <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">220</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr><td class="line">221</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">222</td><td class="hits">79</td><td class="source"> ret<span class="k">.</span>type <span class="k">=</span> type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">223</td><td class="hits">87</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">.</span>type<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">224</td><td class="hits">71</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">.</span>optional<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">225</td><td class="hits">69</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">226</td><td class="hits">69</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tokens<span class="k">.</span>length <span class="k">>=</span> <span class="s">3</span> <span class="k">&amp;&amp;</span></td></tr><tr><td class="line">227</td><td class="hits"></td><td class="source"> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"other"</span> <span class="k">&amp;&amp;</span> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>value <span class="k">===</span> <span class="s">"."</span> <span class="k">&amp;&amp;</span></td></tr><tr><td class="line">228</td><td class="hits"></td><td class="source"> tokens<span class="k">[</span><span class="s">1</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"other"</span> <span class="k">&amp;&amp;</span> tokens<span class="k">[</span><span class="s">1</span><span class="k">].</span>value <span class="k">===</span> <span class="s">"."</span> <span class="k">&amp;&amp;</span></td></tr><tr><td class="line">229</td><td class="hits"></td><td class="source"> tokens<span class="k">[</span><span class="s">2</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"other"</span> <span class="k">&amp;&amp;</span> tokens<span class="k">[</span><span class="s">2</span><span class="k">].</span>value <span class="k">===</span> <span class="s">"."</span></td></tr><tr><td class="line">230</td><td class="hits"></td><td class="source"> <span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">231</td><td class="hits">4</td><td class="source"> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">232</td><td class="hits">4</td><td class="source"> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">233</td><td class="hits">4</td><td class="source"> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">234</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>variadic <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr><td class="line">235</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">236</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">237</td><td class="hits">71</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">238</td><td class="hits">71</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name in argument"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">239</td><td class="hits">71</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">240</td><td class="hits">71</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>optional<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">241</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">242</td><td class="hits">2</td><td class="source"> ret<span class="k">[</span><span class="s">"default"</span><span class="k">]</span> <span class="k">=</span> default_<span class="k">();</span></td></tr><tr><td class="line">243</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">244</td><td class="hits">71</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">245</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">246</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">247</td><td class="hits">47</td><td class="source"> <span class="k">var</span> argument_list <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">248</td><td class="hits">59</td><td class="source"> <span class="k">var</span> arg <span class="k">=</span> argument<span class="k">(),</span> ret <span class="k">=</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">249</td><td class="hits">67</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>arg<span class="k">)</span> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">250</td><td class="hits">51</td><td class="source"> ret<span class="k">.</span>push<span class="k">(</span>arg<span class="k">);</span></td></tr><tr class="hit"> <td class="line">251</td><td class="hits">51</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">252</td><td class="hits">71</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">253</td><td class="hits">122</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">254</td><td class="hits">20</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">255</td><td class="hits">20</td><td class="source"> <span class="k">var</span> nxt <span class="k">=</span> argument<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Trailing comma in arguments list"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">256</td><td class="hits">20</td><td class="source"> ret<span class="k">.</span>push<span class="k">(</span>nxt<span class="k">);</span></td></tr><tr><td class="line">257</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">258</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">259</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">260</td><td class="hits">47</td><td class="source"> <span class="k">var</span> simple_extended_attr <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">261</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">262</td><td class="hits">17</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">263</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>name<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">264</td><td class="hits">17</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">265</td><td class="hits"></td><td class="source"> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">266</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"arguments"</span><span class="k">:</span> <span class="k">null</span></td></tr><tr><td class="line">267</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">268</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">269</td><td class="hits">17</td><td class="source"> <span class="k">var</span> eq <span class="k">=</span> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">270</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>eq<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">271</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">272</td><td class="hits">5</td><td class="source"> ret<span class="k">.</span>rhs <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">273</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">.</span>rhs<span class="k">)</span> <span class="k">return</span> error<span class="k">(</span><span class="s">"No right hand side to extended attribute assignment"</span><span class="k">);</span></td></tr><tr><td class="line">274</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">275</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">276</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">277</td><td class="hits">2</td><td class="source"> ret<span class="k">[</span><span class="s">"arguments"</span><span class="k">]</span> <span class="k">=</span> argument_list<span class="k">();</span></td></tr><tr class="hit"> <td class="line">278</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">279</td><td class="hits">2</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unclosed argument in extended attribute"</span><span class="k">);</span></td></tr><tr><td class="line">280</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">281</td><td class="hits">17</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">282</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">283</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">284</td><td class="hits"></td><td class="source"> <span class="c">// Note: we parse something simpler than the official syntax. It's all that ever</span></td></tr><tr><td class="line">285</td><td class="hits"></td><td class="source"> <span class="c">// seems to be used</span></td></tr><tr class="hit"> <td class="line">286</td><td class="hits">47</td><td class="source"> <span class="k">var</span> extended_attrs <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">287</td><td class="hits">415</td><td class="source"> <span class="k">var</span> eas <span class="k">=</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">288</td><td class="hits">415</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">289</td><td class="hits">815</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"["</span><span class="k">))</span> <span class="k">return</span> eas<span class="k">;</span></td></tr><tr class="hit"> <td class="line">290</td><td class="hits">15</td><td class="source"> eas<span class="k">[</span><span class="s">0</span><span class="k">]</span> <span class="k">=</span> simple_extended_attr<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Extended attribute with not content"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">291</td><td class="hits">15</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">292</td><td class="hits">15</td><td class="source"> <span class="k">while</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">293</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">294</td><td class="hits">2</td><td class="source"> eas<span class="k">.</span>push<span class="k">(</span>simple_extended_attr<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Trailing comma in extended attribute"</span><span class="k">));</span></td></tr><tr class="hit"> <td class="line">295</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr><td class="line">296</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">297</td><td class="hits">15</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"]"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No end of extended attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">298</td><td class="hits">15</td><td class="source"> <span class="k">return</span> eas<span class="k">;</span></td></tr><tr><td class="line">299</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">300</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">301</td><td class="hits">47</td><td class="source"> <span class="k">var</span> default_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">302</td><td class="hits">11</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">303</td><td class="hits">11</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">304</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">305</td><td class="hits">5</td><td class="source"> <span class="k">var</span> def <span class="k">=</span> const_value<span class="k">();</span></td></tr><tr class="hit"> <td class="line">306</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> def <span class="k">!==</span> <span class="s">"undefined"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">307</td><td class="hits">3</td><td class="source"> <span class="k">return</span> def<span class="k">;</span></td></tr><tr><td class="line">308</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">309</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">310</td><td class="hits">2</td><td class="source"> <span class="k">var</span> str <span class="k">=</span> consume<span class="k">(</span>STR<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No value for default"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">311</td><td class="hits">2</td><td class="source"> <span class="k">return</span> str<span class="k">;</span></td></tr><tr><td class="line">312</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">313</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">314</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">315</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">316</td><td class="hits">47</td><td class="source"> <span class="k">var</span> const_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">317</td><td class="hits">180</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">318</td><td class="hits">348</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"const"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">319</td><td class="hits">12</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"const"</span><span class="k">,</span> nullable<span class="k">:</span> <span class="k">false</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">320</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">321</td><td class="hits">12</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> primitive_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">322</td><td class="hits">12</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>typ<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">323</td><td class="hits">0</td><td class="source"> typ <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type for const"</span><span class="k">);</span></td></tr><tr class="miss"> <td class="line">324</td><td class="hits">0</td><td class="source"> typ <span class="k">=</span> typ<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">325</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">326</td><td class="hits">12</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> typ<span class="k">;</span></td></tr><tr class="hit"> <td class="line">327</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">328</td><td class="hits">12</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"?"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">329</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>nullable <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">330</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr><td class="line">331</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">332</td><td class="hits">12</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">333</td><td class="hits">12</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">334</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">335</td><td class="hits">12</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No value assignment for const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">336</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">337</td><td class="hits">12</td><td class="source"> <span class="k">var</span> cnt <span class="k">=</span> const_value<span class="k">();</span></td></tr><tr class="hit"> <td class="line">338</td><td class="hits">24</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> cnt <span class="k">!==</span> <span class="s">"undefined"</span><span class="k">)</span> ret<span class="k">.</span>value <span class="k">=</span> cnt<span class="k">;</span></td></tr><tr class="miss"> <td class="line">339</td><td class="hits">0</td><td class="source"> <span class="k">else</span> error<span class="k">(</span><span class="s">"No value for const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">340</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">341</td><td class="hits">12</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">342</td><td class="hits">12</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">343</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">344</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">345</td><td class="hits">47</td><td class="source"> <span class="k">var</span> inheritance <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">346</td><td class="hits">89</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">347</td><td class="hits">89</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">":"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">348</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">349</td><td class="hits">9</td><td class="source"> <span class="k">var</span> inh <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error <span class="k">(</span><span class="s">"No type in inheritance"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">350</td><td class="hits">9</td><td class="source"> <span class="k">return</span> inh<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">351</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">352</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">353</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">354</td><td class="hits">47</td><td class="source"> <span class="k">var</span> operation_rest <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>ret<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">355</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">356</td><td class="hits">57</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">)</span> ret <span class="k">=</span> <span class="k">{}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">357</td><td class="hits">56</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">358</td><td class="hits">56</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name <span class="k">?</span> name<span class="k">.</span>value <span class="k">:</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">359</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">360</td><td class="hits">56</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Invalid operation"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">361</td><td class="hits">56</td><td class="source"> ret<span class="k">[</span><span class="s">"arguments"</span><span class="k">]</span> <span class="k">=</span> argument_list<span class="k">();</span></td></tr><tr class="hit"> <td class="line">362</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">363</td><td class="hits">56</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated operation"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">364</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">365</td><td class="hits">56</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated operation"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">366</td><td class="hits">56</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">367</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">368</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">369</td><td class="hits">47</td><td class="source"> <span class="k">var</span> callback <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">370</td><td class="hits">144</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">371</td><td class="hits">144</td><td class="source"> <span class="k">var</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">372</td><td class="hits">286</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"callback"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">373</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">374</td><td class="hits">2</td><td class="source"> <span class="k">var</span> tok <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">375</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tok<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">376</td><td class="hits">1</td><td class="source"> tokens<span class="k">.</span>unshift<span class="k">(</span>tok<span class="k">);</span></td></tr><tr class="hit"> <td class="line">377</td><td class="hits">1</td><td class="source"> ret <span class="k">=</span> interface_<span class="k">();</span></td></tr><tr class="hit"> <td class="line">378</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>type <span class="k">=</span> <span class="s">"callback interface"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">379</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">380</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">381</td><td class="hits">1</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">382</td><td class="hits">1</td><td class="source"> ret <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"callback"</span><span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">383</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">384</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No assignment in callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">385</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">386</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">387</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">388</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No arguments in callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">389</td><td class="hits">1</td><td class="source"> ret<span class="k">[</span><span class="s">"arguments"</span><span class="k">]</span> <span class="k">=</span> argument_list<span class="k">();</span></td></tr><tr class="hit"> <td class="line">390</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">391</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">392</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">393</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">394</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">395</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">396</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">397</td><td class="hits">47</td><td class="source"> <span class="k">var</span> attribute <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">398</td><td class="hits">154</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">399</td><td class="hits">154</td><td class="source"> <span class="k">var</span> grabbed <span class="k">=</span> <span class="k">[]</span></td></tr><tr><td class="line">400</td><td class="hits"></td><td class="source"> <span class="k">,</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">401</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"attribute"</span></td></tr><tr><td class="line">402</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"static"</span><span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">403</td><td class="hits"></td><td class="source"> <span class="k">,</span> stringifier<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">404</td><td class="hits"></td><td class="source"> <span class="k">,</span> inherit<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">405</td><td class="hits"></td><td class="source"> <span class="k">,</span> readonly<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">406</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">407</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"static"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">408</td><td class="hits">2</td><td class="source"> ret<span class="k">[</span><span class="s">"static"</span><span class="k">]</span> <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">409</td><td class="hits">2</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr><td class="line">410</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">411</td><td class="hits">152</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"stringifier"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">412</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>stringifier <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">413</td><td class="hits">4</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr><td class="line">414</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">415</td><td class="hits">154</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">416</td><td class="hits">159</td><td class="source"> <span class="k">if</span> <span class="k">(</span>w<span class="k">)</span> grabbed<span class="k">.</span>push<span class="k">(</span>w<span class="k">);</span></td></tr><tr class="hit"> <td class="line">417</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"inherit"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">418</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">[</span><span class="s">"static"</span><span class="k">]</span> <span class="k">||</span> ret<span class="k">.</span>stringifier<span class="k">)</span> error<span class="k">(</span><span class="s">"Cannot have a static or stringifier inherit"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">419</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>inherit <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">420</td><td class="hits">1</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr class="hit"> <td class="line">421</td><td class="hits">1</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">422</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>w<span class="k">)</span> grabbed<span class="k">.</span>push<span class="k">(</span>w<span class="k">);</span></td></tr><tr><td class="line">423</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">424</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"readonly"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">425</td><td class="hits">32</td><td class="source"> ret<span class="k">.</span>readonly <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">426</td><td class="hits">32</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr class="hit"> <td class="line">427</td><td class="hits">32</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">428</td><td class="hits">64</td><td class="source"> <span class="k">if</span> <span class="k">(</span>w<span class="k">)</span> grabbed<span class="k">.</span>push<span class="k">(</span>w<span class="k">);</span></td></tr><tr><td class="line">429</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">430</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"attribute"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">431</td><td class="hits">60</td><td class="source"> tokens <span class="k">=</span> grabbed<span class="k">.</span>concat<span class="k">(</span>tokens<span class="k">);</span></td></tr><tr class="hit"> <td class="line">432</td><td class="hits">60</td><td class="source"> <span class="k">return</span><span class="k">;</span></td></tr><tr><td class="line">433</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">434</td><td class="hits">94</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">435</td><td class="hits">94</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type in attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">436</td><td class="hits">94</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>idlType<span class="k">.</span>sequence<span class="k">)</span> error<span class="k">(</span><span class="s">"Attributes cannot accept sequence types"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">437</td><td class="hits">94</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">438</td><td class="hits">94</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name in attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">439</td><td class="hits">94</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">440</td><td class="hits">94</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">441</td><td class="hits">94</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">442</td><td class="hits">94</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">443</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">444</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">445</td><td class="hits">47</td><td class="source"> <span class="k">var</span> return_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">446</td><td class="hits">61</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">447</td><td class="hits">61</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>typ<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">448</td><td class="hits">0</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"void"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">449</td><td class="hits">0</td><td class="source"> <span class="k">return</span> <span class="s">"void"</span><span class="k">;</span></td></tr><tr><td class="line">450</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="miss"> <td class="line">451</td><td class="hits">0</td><td class="source"> <span class="k">else</span> error<span class="k">(</span><span class="s">"No return type"</span><span class="k">);</span></td></tr><tr><td class="line">452</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">453</td><td class="hits">61</td><td class="source"> <span class="k">return</span> typ<span class="k">;</span></td></tr><tr><td class="line">454</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">455</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">456</td><td class="hits">47</td><td class="source"> <span class="k">var</span> operation <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">457</td><td class="hits">60</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">458</td><td class="hits">60</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">459</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"operation"</span></td></tr><tr><td class="line">460</td><td class="hits"></td><td class="source"> <span class="k">,</span> getter<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">461</td><td class="hits"></td><td class="source"> <span class="k">,</span> setter<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">462</td><td class="hits"></td><td class="source"> <span class="k">,</span> creator<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">463</td><td class="hits"></td><td class="source"> <span class="k">,</span> deleter<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">464</td><td class="hits"></td><td class="source"> <span class="k">,</span> legacycaller<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">465</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"static"</span><span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">466</td><td class="hits"></td><td class="source"> <span class="k">,</span> stringifier<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">467</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">468</td><td class="hits">60</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">469</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">470</td><td class="hits">87</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"getter"</span><span class="k">))</span> ret<span class="k">.</span>getter <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">471</td><td class="hits">74</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"setter"</span><span class="k">))</span> ret<span class="k">.</span>setter <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">472</td><td class="hits">65</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"creator"</span><span class="k">))</span> ret<span class="k">.</span>creator <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">473</td><td class="hits">65</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"deleter"</span><span class="k">))</span> ret<span class="k">.</span>deleter <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">474</td><td class="hits">62</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"legacycaller"</span><span class="k">))</span> ret<span class="k">.</span>legacycaller <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">475</td><td class="hits">60</td><td class="source"> <span class="k">else</span> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">476</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">477</td><td class="hits">60</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>getter <span class="k">||</span> ret<span class="k">.</span>setter <span class="k">||</span> ret<span class="k">.</span>creator <span class="k">||</span> ret<span class="k">.</span>deleter <span class="k">||</span> ret<span class="k">.</span>legacycaller<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">478</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">479</td><td class="hits">17</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">480</td><td class="hits">17</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">481</td><td class="hits">17</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">482</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">483</td><td class="hits">43</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"static"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">484</td><td class="hits">1</td><td class="source"> ret<span class="k">[</span><span class="s">"static"</span><span class="k">]</span> <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">485</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">486</td><td class="hits">1</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">487</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">488</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">489</td><td class="hits">42</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"stringifier"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">490</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>stringifier <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">491</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">492</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">))</span> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">493</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">494</td><td class="hits">2</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">495</td><td class="hits">2</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">496</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">497</td><td class="hits">39</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">498</td><td class="hits">39</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">499</td><td class="hits">39</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"iterator"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">500</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">501</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>type <span class="k">=</span> <span class="s">"iterator"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">502</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"object"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">503</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>iteratorObject <span class="k">=</span> <span class="s">"object"</span><span class="k">;</span></td></tr><tr><td class="line">504</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">505</td><td class="hits">3</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">506</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">507</td><td class="hits">2</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No right hand side in iterator"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">508</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>iteratorObject <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">509</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">510</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">511</td><td class="hits">4</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated iterator"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">512</td><td class="hits">4</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">513</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">514</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">515</td><td class="hits">35</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">516</td><td class="hits">35</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">517</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">518</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">519</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">520</td><td class="hits">47</td><td class="source"> <span class="k">var</span> identifiers <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>arr<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">521</td><td class="hits">5</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">522</td><td class="hits">11</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">523</td><td class="hits">11</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">524</td><td class="hits">6</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">525</td><td class="hits">6</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Trailing comma in identifiers list"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">526</td><td class="hits">6</td><td class="source"> arr<span class="k">.</span>push<span class="k">(</span>name<span class="k">.</span>value<span class="k">);</span></td></tr><tr><td class="line">527</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">528</td><td class="hits">5</td><td class="source"> <span class="k">else</span> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">529</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">530</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">531</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">532</td><td class="hits">47</td><td class="source"> <span class="k">var</span> serialiser <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">533</td><td class="hits">164</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">534</td><td class="hits">318</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"serializer"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">535</td><td class="hits">10</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"serializer"</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">536</td><td class="hits">10</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">537</td><td class="hits">10</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">538</td><td class="hits">8</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">539</td><td class="hits">8</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">540</td><td class="hits">5</td><td class="source"> ret<span class="k">.</span>patternMap <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">541</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">542</td><td class="hits">5</td><td class="source"> <span class="k">var</span> id <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">543</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(</span>id <span class="k">&amp;&amp;</span> id<span class="k">.</span>value <span class="k">===</span> <span class="s">"getter"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">544</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span><span class="s">"getter"</span><span class="k">];</span></td></tr><tr><td class="line">545</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">546</td><td class="hits">4</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>id <span class="k">&amp;&amp;</span> id<span class="k">.</span>value <span class="k">===</span> <span class="s">"inherit"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">547</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span><span class="s">"inherit"</span><span class="k">];</span></td></tr><tr class="hit"> <td class="line">548</td><td class="hits">2</td><td class="source"> identifiers<span class="k">(</span>ret<span class="k">.</span>names<span class="k">);</span></td></tr><tr><td class="line">549</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">550</td><td class="hits">2</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>id<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">551</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span>id<span class="k">.</span>value<span class="k">];</span></td></tr><tr class="hit"> <td class="line">552</td><td class="hits">2</td><td class="source"> identifiers<span class="k">(</span>ret<span class="k">.</span>names<span class="k">);</span></td></tr><tr><td class="line">553</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">554</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">555</td><td class="hits">0</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[];</span></td></tr><tr><td class="line">556</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">557</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">558</td><td class="hits">5</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated serializer pattern map"</span><span class="k">);</span></td></tr><tr><td class="line">559</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">560</td><td class="hits">3</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"["</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">561</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>patternList <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">562</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">563</td><td class="hits">2</td><td class="source"> <span class="k">var</span> id <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">564</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>id <span class="k">&amp;&amp;</span> id<span class="k">.</span>value <span class="k">===</span> <span class="s">"getter"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">565</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span><span class="s">"getter"</span><span class="k">];</span></td></tr><tr><td class="line">566</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">567</td><td class="hits">1</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>id<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">568</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span>id<span class="k">.</span>value<span class="k">];</span></td></tr><tr class="hit"> <td class="line">569</td><td class="hits">1</td><td class="source"> identifiers<span class="k">(</span>ret<span class="k">.</span>names<span class="k">);</span></td></tr><tr><td class="line">570</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">571</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">572</td><td class="hits">0</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[];</span></td></tr><tr><td class="line">573</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">574</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">575</td><td class="hits">2</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"]"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated serializer pattern list"</span><span class="k">);</span></td></tr><tr><td class="line">576</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">577</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">578</td><td class="hits">1</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Invalid serializer"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">579</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">580</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">581</td><td class="hits">8</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">582</td><td class="hits">8</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated serializer"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">583</td><td class="hits">8</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">584</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">585</td><td class="hits">2</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr><td class="line">586</td><td class="hits"></td><td class="source"> <span class="c">// noop, just parsing</span></td></tr><tr><td class="line">587</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">588</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">589</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">590</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">591</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>operation <span class="k">=</span> operation_rest<span class="k">();</span></td></tr><tr><td class="line">592</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">593</td><td class="hits">2</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">594</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">595</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">596</td><td class="hits">47</td><td class="source"> <span class="k">var</span> interface_ <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>isPartial<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">597</td><td class="hits">144</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">598</td><td class="hits">210</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"interface"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">599</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">600</td><td class="hits">78</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">601</td><td class="hits">78</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">602</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"interface"</span></td></tr><tr><td class="line">603</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">604</td><td class="hits"></td><td class="source"> <span class="k">,</span> partial<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">605</td><td class="hits"></td><td class="source"> <span class="k">,</span> members<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">606</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">607</td><td class="hits">155</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>isPartial<span class="k">)</span> ret<span class="k">.</span>inheritance <span class="k">=</span> inheritance<span class="k">()</span> <span class="k">||</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">608</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">609</td><td class="hits">78</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Bodyless interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">610</td><td class="hits">78</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">611</td><td class="hits">251</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">612</td><td class="hits">251</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">613</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">614</td><td class="hits">78</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Missing semicolon after interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">615</td><td class="hits">78</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">616</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">617</td><td class="hits">173</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">618</td><td class="hits">173</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">619</td><td class="hits">173</td><td class="source"> <span class="k">var</span> cnt <span class="k">=</span> const_<span class="k">();</span></td></tr><tr class="hit"> <td class="line">620</td><td class="hits">173</td><td class="source"> <span class="k">if</span> <span class="k">(</span>cnt<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">621</td><td class="hits">9</td><td class="source"> cnt<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">622</td><td class="hits">9</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span>cnt<span class="k">);</span></td></tr><tr class="hit"> <td class="line">623</td><td class="hits">9</td><td class="source"> <span class="k">continue</span><span class="k">;</span></td></tr><tr><td class="line">624</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">625</td><td class="hits">164</td><td class="source"> <span class="k">var</span> mem <span class="k">=</span> serialiser<span class="k">()</span> <span class="k">||</span> attribute<span class="k">()</span> <span class="k">||</span> operation<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unknown member"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">626</td><td class="hits">164</td><td class="source"> mem<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">627</td><td class="hits">164</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span>mem<span class="k">);</span></td></tr><tr><td class="line">628</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">629</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">630</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">631</td><td class="hits">47</td><td class="source"> <span class="k">var</span> partial <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">632</td><td class="hits">66</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">633</td><td class="hits">130</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"partial"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">634</td><td class="hits">2</td><td class="source"> <span class="k">var</span> thing <span class="k">=</span> dictionary<span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">||</span> interface_<span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Partial doesn't apply to anything"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">635</td><td class="hits">2</td><td class="source"> thing<span class="k">.</span>partial <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">636</td><td class="hits">2</td><td class="source"> <span class="k">return</span> thing<span class="k">;</span></td></tr><tr><td class="line">637</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">638</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">639</td><td class="hits">47</td><td class="source"> <span class="k">var</span> dictionary <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>isPartial<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">640</td><td class="hits">66</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">641</td><td class="hits">128</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"dictionary"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">642</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">643</td><td class="hits">4</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for dictionary"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">644</td><td class="hits">4</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">645</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"dictionary"</span></td></tr><tr><td class="line">646</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">647</td><td class="hits"></td><td class="source"> <span class="k">,</span> partial<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">648</td><td class="hits"></td><td class="source"> <span class="k">,</span> members<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">649</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">650</td><td class="hits">7</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>isPartial<span class="k">)</span> ret<span class="k">.</span>inheritance <span class="k">=</span> inheritance<span class="k">()</span> <span class="k">||</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">651</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">652</td><td class="hits">4</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Bodyless dictionary"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">653</td><td class="hits">4</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">654</td><td class="hits">13</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">655</td><td class="hits">13</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">656</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">657</td><td class="hits">4</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Missing semicolon after dictionary"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">658</td><td class="hits">4</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">659</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">660</td><td class="hits">9</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">661</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">662</td><td class="hits">9</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type for dictionary member"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">663</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">664</td><td class="hits">9</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for dictionary member"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">665</td><td class="hits">9</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span><span class="k">{</span></td></tr><tr><td class="line">666</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"field"</span></td></tr><tr><td class="line">667</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">668</td><td class="hits"></td><td class="source"> <span class="k">,</span> idlType<span class="k">:</span> typ</td></tr><tr><td class="line">669</td><td class="hits"></td><td class="source"> <span class="k">,</span> extAttrs<span class="k">:</span> ea</td></tr><tr><td class="line">670</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"default"</span><span class="k">:</span> default_<span class="k">()</span></td></tr><tr><td class="line">671</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">672</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">673</td><td class="hits">9</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated dictionary member"</span><span class="k">);</span></td></tr><tr><td class="line">674</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">675</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">676</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">677</td><td class="hits">47</td><td class="source"> <span class="k">var</span> exception <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">678</td><td class="hits">61</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">679</td><td class="hits">113</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"exception"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">680</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">681</td><td class="hits">9</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for exception"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">682</td><td class="hits">9</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">683</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"exception"</span></td></tr><tr><td class="line">684</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">685</td><td class="hits"></td><td class="source"> <span class="k">,</span> members<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">686</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">687</td><td class="hits">9</td><td class="source"> ret<span class="k">.</span>inheritance <span class="k">=</span> inheritance<span class="k">()</span> <span class="k">||</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">688</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">689</td><td class="hits">9</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Bodyless exception"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">690</td><td class="hits">9</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">691</td><td class="hits">16</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">692</td><td class="hits">16</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">693</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">694</td><td class="hits">9</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Missing semicolon after exception"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">695</td><td class="hits">9</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">696</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">697</td><td class="hits">7</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">698</td><td class="hits">7</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">699</td><td class="hits">7</td><td class="source"> <span class="k">var</span> cnt <span class="k">=</span> const_<span class="k">();</span></td></tr><tr class="hit"> <td class="line">700</td><td class="hits">7</td><td class="source"> <span class="k">if</span> <span class="k">(</span>cnt<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">701</td><td class="hits">3</td><td class="source"> cnt<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">702</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span>cnt<span class="k">);</span></td></tr><tr><td class="line">703</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">704</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">705</td><td class="hits">4</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">706</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">707</td><td class="hits">4</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">708</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">709</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>typ <span class="k">||</span> <span class="k">!</span>name <span class="k">||</span> <span class="k">!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">))</span> error<span class="k">(</span><span class="s">"Unknown member in exception body"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">710</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span><span class="k">{</span></td></tr><tr><td class="line">711</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"field"</span></td></tr><tr><td class="line">712</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">713</td><td class="hits"></td><td class="source"> <span class="k">,</span> idlType<span class="k">:</span> typ</td></tr><tr><td class="line">714</td><td class="hits"></td><td class="source"> <span class="k">,</span> extAttrs<span class="k">:</span> ea</td></tr><tr><td class="line">715</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">);</span></td></tr><tr><td class="line">716</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">717</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">718</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">719</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">720</td><td class="hits">47</td><td class="source"> <span class="k">var</span> enum_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">721</td><td class="hits">52</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">722</td><td class="hits">103</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"enum"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">723</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">724</td><td class="hits">1</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">725</td><td class="hits">1</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">726</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"enum"</span></td></tr><tr><td class="line">727</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">728</td><td class="hits"></td><td class="source"> <span class="k">,</span> values<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">729</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">730</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">731</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No curly for enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">732</td><td class="hits">1</td><td class="source"> <span class="k">var</span> saw_comma <span class="k">=</span> <span class="k">false</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">733</td><td class="hits">1</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">734</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">735</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">736</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">737</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span>saw_comma<span class="k">)</span> error<span class="k">(</span><span class="s">"Trailing comma in enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">738</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No semicolon after enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">739</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">740</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">741</td><td class="hits">3</td><td class="source"> <span class="k">var</span> val <span class="k">=</span> consume<span class="k">(</span>STR<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unexpected value in enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">742</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>values<span class="k">.</span>push<span class="k">(</span>val<span class="k">.</span>value<span class="k">.</span>replace<span class="k">(</span><span class="s">/"/g</span><span class="k">,</span> <span class="s">""</span><span class="k">));</span></td></tr><tr class="hit"> <td class="line">743</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">744</td><td class="hits">3</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">745</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">746</td><td class="hits">2</td><td class="source"> saw_comma <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr><td class="line">747</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">748</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">749</td><td class="hits">1</td><td class="source"> saw_comma <span class="k">=</span> <span class="k">false</span><span class="k">;</span></td></tr><tr><td class="line">750</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">751</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">752</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">753</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">754</td><td class="hits">47</td><td class="source"> <span class="k">var</span> typedef <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">755</td><td class="hits">51</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">756</td><td class="hits">99</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"typedef"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">757</td><td class="hits">3</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">758</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"typedef"</span></td></tr><tr><td class="line">759</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">760</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">761</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>extAttrs <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">762</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">763</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type in typedef"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">764</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">765</td><td class="hits">3</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name in typedef"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">766</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">767</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">768</td><td class="hits">3</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated typedef"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">769</td><td class="hits">3</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">770</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">771</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">772</td><td class="hits">47</td><td class="source"> <span class="k">var</span> implements_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">773</td><td class="hits">48</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">774</td><td class="hits">48</td><td class="source"> <span class="k">var</span> target <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">775</td><td class="hits">95</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>target<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">776</td><td class="hits">1</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">777</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"implements"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">778</td><td class="hits">1</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">779</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"implements"</span></td></tr><tr><td class="line">780</td><td class="hits"></td><td class="source"> <span class="k">,</span> target<span class="k">:</span> target<span class="k">.</span>value</td></tr><tr><td class="line">781</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">782</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">783</td><td class="hits">1</td><td class="source"> <span class="k">var</span> imp <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Incomplete implements statement"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">784</td><td class="hits">1</td><td class="source"> ret<span class="k">[</span><span class="s">"implements"</span><span class="k">]</span> <span class="k">=</span> imp<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">785</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">786</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No terminating ; for implements statement"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">787</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">788</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">789</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr><td class="line">790</td><td class="hits"></td><td class="source"> <span class="c">// rollback</span></td></tr><tr class="miss"> <td class="line">791</td><td class="hits">0</td><td class="source"> tokens<span class="k">.</span>unshift<span class="k">(</span>w<span class="k">);</span></td></tr><tr class="miss"> <td class="line">792</td><td class="hits">0</td><td class="source"> tokens<span class="k">.</span>unshift<span class="k">(</span>target<span class="k">);</span></td></tr><tr><td class="line">793</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">794</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">795</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">796</td><td class="hits">47</td><td class="source"> <span class="k">var</span> definition <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">797</td><td class="hits">144</td><td class="source"> <span class="k">return</span> callback<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">798</td><td class="hits"></td><td class="source"> interface_<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">799</td><td class="hits"></td><td class="source"> partial<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">800</td><td class="hits"></td><td class="source"> dictionary<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">801</td><td class="hits"></td><td class="source"> exception<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">802</td><td class="hits"></td><td class="source"> enum_<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">803</td><td class="hits"></td><td class="source"> typedef<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">804</td><td class="hits"></td><td class="source"> implements_<span class="k">()</span></td></tr><tr><td class="line">805</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr><td class="line">806</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">807</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">808</td><td class="hits">47</td><td class="source"> <span class="k">var</span> definitions <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">809</td><td class="hits">47</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>tokens<span class="k">.</span>length<span class="k">)</span> <span class="k">return</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">810</td><td class="hits">47</td><td class="source"> <span class="k">var</span> defs <span class="k">=</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">811</td><td class="hits">47</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">812</td><td class="hits">144</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">()</span></td></tr><tr><td class="line">813</td><td class="hits"></td><td class="source"> <span class="k">,</span> def <span class="k">=</span> definition<span class="k">();</span></td></tr><tr class="hit"> <td class="line">814</td><td class="hits">144</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>def<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">815</td><td class="hits">47</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ea<span class="k">.</span>length<span class="k">)</span> error<span class="k">(</span><span class="s">"Stray extended attributes"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">816</td><td class="hits">47</td><td class="source"> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">817</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">818</td><td class="hits">97</td><td class="source"> def<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">819</td><td class="hits">97</td><td class="source"> defs<span class="k">.</span>push<span class="k">(</span>def<span class="k">);</span></td></tr><tr><td class="line">820</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">821</td><td class="hits">47</td><td class="source"> <span class="k">return</span> defs<span class="k">;</span></td></tr><tr><td class="line">822</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">823</td><td class="hits">47</td><td class="source"> <span class="k">var</span> res <span class="k">=</span> definitions<span class="k">();</span></td></tr><tr class="hit"> <td class="line">824</td><td class="hits">47</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tokens<span class="k">.</span>length<span class="k">)</span> error<span class="k">(</span><span class="s">"Unrecognised tokens"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">825</td><td class="hits">47</td><td class="source"> <span class="k">return</span> res<span class="k">;</span></td></tr><tr><td class="line">826</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">827</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">828</td><td class="hits">1</td><td class="source"> <span class="k">var</span> obj <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">829</td><td class="hits"></td><td class="source"> parse<span class="k">:</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">830</td><td class="hits">47</td><td class="source"> <span class="k">var</span> tokens <span class="k">=</span> tokenise<span class="k">(</span>str<span class="k">);</span></td></tr><tr><td class="line">831</td><td class="hits"></td><td class="source"> <span class="c">// console.log(tokens);</span></td></tr><tr class="hit"> <td class="line">832</td><td class="hits">47</td><td class="source"> <span class="k">return</span> parse<span class="k">(</span>tokens<span class="k">);</span></td></tr><tr><td class="line">833</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">834</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">835</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> module <span class="k">!==</span> <span class="s">"undefined"</span> <span class="k">&amp;&amp;</span> module<span class="k">.</span>exports<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">836</td><td class="hits">1</td><td class="source"> module<span class="k">.</span>exports <span class="k">=</span> obj<span class="k">;</span></td></tr><tr><td class="line">837</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">838</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">839</td><td class="hits">0</td><td class="source"> window<span class="k">.</span>WebIDL2 <span class="k">=</span> obj<span class="k">;</span></td></tr><tr><td class="line">840</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">841</td><td class="hits"></td><td class="source"><span class="k">}</span><span class="k">());</span></td></tr></tbody></table></div></div></div></body></html>
diff --git a/testing/web-platform/tests/resources/webidl2/index.js b/testing/web-platform/tests/resources/webidl2/index.js
new file mode 100644
index 000000000..09f9eb46a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/index.js
@@ -0,0 +1 @@
+module.exports = require("./lib/webidl2.js");
diff --git a/testing/web-platform/tests/resources/webidl2/lib/webidl2.js b/testing/web-platform/tests/resources/webidl2/lib/webidl2.js
new file mode 100644
index 000000000..9e504fc6e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/lib/webidl2.js
@@ -0,0 +1,1012 @@
+
+
+(function () {
+ var tokenise = function (str) {
+ var tokens = []
+ , re = {
+ "float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/
+ , "integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/
+ , "identifier": /^[A-Z_a-z][0-9A-Z_a-z]*/
+ , "string": /^"[^"]*"/
+ , "whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/
+ , "other": /^[^\t\n\r 0-9A-Z_a-z]/
+ }
+ , types = []
+ ;
+ for (var k in re) types.push(k);
+ while (str.length > 0) {
+ var matched = false;
+ for (var i = 0, n = types.length; i < n; i++) {
+ var type = types[i];
+ str = str.replace(re[type], function (tok) {
+ tokens.push({ type: type, value: tok });
+ matched = true;
+ return "";
+ });
+ if (matched) break;
+ }
+ if (matched) continue;
+ throw new Error("Token stream not progressing");
+ }
+ return tokens;
+ };
+
+ var parse = function (tokens, opt) {
+ var line = 1;
+ tokens = tokens.slice();
+
+ var FLOAT = "float"
+ , INT = "integer"
+ , ID = "identifier"
+ , STR = "string"
+ , OTHER = "other"
+ ;
+
+ var WebIDLParseError = function (str, line, input, tokens) {
+ this.message = str;
+ this.line = line;
+ this.input = input;
+ this.tokens = tokens;
+ };
+ WebIDLParseError.prototype.toString = function () {
+ return this.message + ", line " + this.line + " (tokens: '" + this.input + "')\n" +
+ JSON.stringify(this.tokens, null, 4);
+ };
+
+ var error = function (str) {
+ var tok = "", numTokens = 0, maxTokens = 5;
+ while (numTokens < maxTokens && tokens.length > numTokens) {
+ tok += tokens[numTokens].value;
+ numTokens++;
+ }
+ throw new WebIDLParseError(str, line, tok, tokens.slice(0, 5));
+ };
+
+ var last_token = null;
+
+ var consume = function (type, value) {
+ if (!tokens.length || tokens[0].type !== type) return;
+ if (typeof value === "undefined" || tokens[0].value === value) {
+ last_token = tokens.shift();
+ if (type === ID) last_token.value = last_token.value.replace(/^_/, "");
+ return last_token;
+ }
+ };
+
+ var ws = function () {
+ if (!tokens.length) return;
+ if (tokens[0].type === "whitespace") {
+ var t = tokens.shift();
+ t.value.replace(/\n/g, function (m) { line++; return m; });
+ return t;
+ }
+ };
+
+ var all_ws = function (store, pea) { // pea == post extended attribute, tpea = same for types
+ var t = { type: "whitespace", value: "" };
+ while (true) {
+ var w = ws();
+ if (!w) break;
+ t.value += w.value;
+ }
+ if (t.value.length > 0) {
+ if (store) {
+ var w = t.value
+ , re = {
+ "ws": /^([\t\n\r ]+)/
+ , "line-comment": /^\/\/(.*)\n?/m
+ , "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\//
+ }
+ , wsTypes = []
+ ;
+ for (var k in re) wsTypes.push(k);
+ while (w.length) {
+ var matched = false;
+ for (var i = 0, n = wsTypes.length; i < n; i++) {
+ var type = wsTypes[i];
+ w = w.replace(re[type], function (tok, m1) {
+ store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 });
+ matched = true;
+ return "";
+ });
+ if (matched) break;
+ }
+ if (matched) continue;
+ throw new Error("Surprising white space construct."); // this shouldn't happen
+ }
+ }
+ return t;
+ }
+ };
+
+ var integer_type = function () {
+ var ret = "";
+ all_ws();
+ if (consume(ID, "unsigned")) ret = "unsigned ";
+ all_ws();
+ if (consume(ID, "short")) return ret + "short";
+ if (consume(ID, "long")) {
+ ret += "long";
+ all_ws();
+ if (consume(ID, "long")) return ret + " long";
+ return ret;
+ }
+ if (ret) error("Failed to parse integer type");
+ };
+
+ var float_type = function () {
+ var ret = "";
+ all_ws();
+ if (consume(ID, "unrestricted")) ret = "unrestricted ";
+ all_ws();
+ if (consume(ID, "float")) return ret + "float";
+ if (consume(ID, "double")) return ret + "double";
+ if (ret) error("Failed to parse float type");
+ };
+
+ var primitive_type = function () {
+ var num_type = integer_type() || float_type();
+ if (num_type) return num_type;
+ all_ws();
+ if (consume(ID, "boolean")) return "boolean";
+ if (consume(ID, "byte")) return "byte";
+ if (consume(ID, "octet")) return "octet";
+ };
+
+ var const_value = function () {
+ if (consume(ID, "true")) return { type: "boolean", value: true };
+ if (consume(ID, "false")) return { type: "boolean", value: false };
+ if (consume(ID, "null")) return { type: "null" };
+ if (consume(ID, "Infinity")) return { type: "Infinity", negative: false };
+ if (consume(ID, "NaN")) return { type: "NaN" };
+ var ret = consume(FLOAT) || consume(INT);
+ if (ret) return { type: "number", value: 1 * ret.value };
+ var tok = consume(OTHER, "-");
+ if (tok) {
+ if (consume(ID, "Infinity")) return { type: "Infinity", negative: true };
+ else tokens.unshift(tok);
+ }
+ };
+
+ var type_suffix = function (obj) {
+ while (true) {
+ all_ws();
+ if (consume(OTHER, "?")) {
+ if (obj.nullable) error("Can't nullable more than once");
+ obj.nullable = true;
+ }
+ else if (consume(OTHER, "[")) {
+ all_ws();
+ consume(OTHER, "]") || error("Unterminated array type");
+ if (!obj.array) {
+ obj.array = 1;
+ obj.nullableArray = [obj.nullable];
+ }
+ else {
+ obj.array++;
+ obj.nullableArray.push(obj.nullable);
+ }
+ obj.nullable = false;
+ }
+ else return;
+ }
+ };
+
+ var single_type = function () {
+ var prim = primitive_type()
+ , ret = { sequence: false, generic: null, nullable: false, array: false, union: false }
+ , name
+ , value
+ ;
+ if (prim) {
+ ret.idlType = prim;
+ }
+ else if (name = consume(ID)) {
+ value = name.value;
+ all_ws();
+ // Generic types
+ if (consume(OTHER, "<")) {
+ // backwards compat
+ if (value === "sequence") {
+ ret.sequence = true;
+ }
+ ret.generic = value;
+ ret.idlType = type() || error("Error parsing generic type " + value);
+ all_ws();
+ if (!consume(OTHER, ">")) error("Unterminated generic type " + value);
+ type_suffix(ret);
+ return ret;
+ }
+ else {
+ ret.idlType = value;
+ }
+ }
+ else {
+ return;
+ }
+ type_suffix(ret);
+ if (ret.nullable && !ret.array && ret.idlType === "any") error("Type any cannot be made nullable");
+ return ret;
+ };
+
+ var union_type = function () {
+ all_ws();
+ if (!consume(OTHER, "(")) return;
+ var ret = { sequence: false, generic: null, nullable: false, array: false, union: true, idlType: [] };
+ var fst = type() || error("Union type with no content");
+ ret.idlType.push(fst);
+ while (true) {
+ all_ws();
+ if (!consume(ID, "or")) break;
+ var typ = type() || error("No type after 'or' in union type");
+ ret.idlType.push(typ);
+ }
+ if (!consume(OTHER, ")")) error("Unterminated union type");
+ type_suffix(ret);
+ return ret;
+ };
+
+ var type = function () {
+ return single_type() || union_type();
+ };
+
+ var argument = function (store) {
+ var ret = { optional: false, variadic: false };
+ ret.extAttrs = extended_attrs(store);
+ all_ws(store, "pea");
+ var opt_token = consume(ID, "optional");
+ if (opt_token) {
+ ret.optional = true;
+ all_ws();
+ }
+ ret.idlType = type();
+ if (!ret.idlType) {
+ if (opt_token) tokens.unshift(opt_token);
+ return;
+ }
+ var type_token = last_token;
+ if (!ret.optional) {
+ all_ws();
+ if (tokens.length >= 3 &&
+ tokens[0].type === "other" && tokens[0].value === "." &&
+ tokens[1].type === "other" && tokens[1].value === "." &&
+ tokens[2].type === "other" && tokens[2].value === "."
+ ) {
+ tokens.shift();
+ tokens.shift();
+ tokens.shift();
+ ret.variadic = true;
+ }
+ }
+ all_ws();
+ var name = consume(ID);
+ if (!name) {
+ if (opt_token) tokens.unshift(opt_token);
+ tokens.unshift(type_token);
+ return;
+ }
+ ret.name = name.value;
+ if (ret.optional) {
+ all_ws();
+ ret["default"] = default_();
+ }
+ return ret;
+ };
+
+ var argument_list = function (store) {
+ var ret = []
+ , arg = argument(store ? ret : null)
+ ;
+ if (!arg) return;
+ ret.push(arg);
+ while (true) {
+ all_ws(store ? ret : null);
+ if (!consume(OTHER, ",")) return ret;
+ var nxt = argument(store ? ret : null) || error("Trailing comma in arguments list");
+ ret.push(nxt);
+ }
+ };
+
+ var type_pair = function () {
+ all_ws();
+ var k = type();
+ if (!k) return;
+ all_ws()
+ if (!consume(OTHER, ",")) return;
+ all_ws();
+ var v = type();
+ if (!v) return;
+ return [k, v];
+ };
+
+ var simple_extended_attr = function (store) {
+ all_ws();
+ var name = consume(ID);
+ if (!name) return;
+ var ret = {
+ name: name.value
+ , "arguments": null
+ };
+ all_ws();
+ var eq = consume(OTHER, "=");
+ if (eq) {
+ var rhs;
+ all_ws();
+ if (rhs = consume(ID)) {
+ ret.rhs = rhs
+ }
+ else if (consume(OTHER, "(")) {
+ // [Exposed=(Window,Worker)]
+ rhs = [];
+ var id = consume(ID);
+ if (id) {
+ rhs = [id.value];
+ }
+ identifiers(rhs);
+ consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair");
+ ret.rhs = {
+ type: "identifier-list",
+ value: rhs
+ };
+ }
+ if (!ret.rhs) return error("No right hand side to extended attribute assignment");
+ }
+ all_ws();
+ if (consume(OTHER, "(")) {
+ var args, pair;
+ // [Constructor(DOMString str)]
+ if (args = argument_list(store)) {
+ ret["arguments"] = args;
+ }
+ // [MapClass(DOMString, DOMString)]
+ else if (pair = type_pair()) {
+ ret.typePair = pair;
+ }
+ // [Constructor()]
+ else {
+ ret["arguments"] = [];
+ }
+ all_ws();
+ consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair");
+ }
+ return ret;
+ };
+
+ // Note: we parse something simpler than the official syntax. It's all that ever
+ // seems to be used
+ var extended_attrs = function (store) {
+ var eas = [];
+ all_ws(store);
+ if (!consume(OTHER, "[")) return eas;
+ eas[0] = simple_extended_attr(store) || error("Extended attribute with not content");
+ all_ws();
+ while (consume(OTHER, ",")) {
+ eas.push(simple_extended_attr(store) || error("Trailing comma in extended attribute"));
+ all_ws();
+ }
+ consume(OTHER, "]") || error("No end of extended attribute");
+ return eas;
+ };
+
+ var default_ = function () {
+ all_ws();
+ if (consume(OTHER, "=")) {
+ all_ws();
+ var def = const_value();
+ if (def) {
+ return def;
+ }
+ else if (consume(OTHER, "[")) {
+ if (!consume(OTHER, "]")) error("Default sequence value must be empty");
+ return { type: "sequence", value: [] };
+ }
+ else {
+ var str = consume(STR) || error("No value for default");
+ str.value = str.value.replace(/^"/, "").replace(/"$/, "");
+ return str;
+ }
+ }
+ };
+
+ var const_ = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "const")) return;
+ var ret = { type: "const", nullable: false };
+ all_ws();
+ var typ = primitive_type();
+ if (!typ) {
+ typ = consume(ID) || error("No type for const");
+ typ = typ.value;
+ }
+ ret.idlType = typ;
+ all_ws();
+ if (consume(OTHER, "?")) {
+ ret.nullable = true;
+ all_ws();
+ }
+ var name = consume(ID) || error("No name for const");
+ ret.name = name.value;
+ all_ws();
+ consume(OTHER, "=") || error("No value assignment for const");
+ all_ws();
+ var cnt = const_value();
+ if (cnt) ret.value = cnt;
+ else error("No value for const");
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated const");
+ return ret;
+ };
+
+ var inheritance = function () {
+ all_ws();
+ if (consume(OTHER, ":")) {
+ all_ws();
+ var inh = consume(ID) || error ("No type in inheritance");
+ return inh.value;
+ }
+ };
+
+ var operation_rest = function (ret, store) {
+ all_ws();
+ if (!ret) ret = {};
+ var name = consume(ID);
+ ret.name = name ? name.value : null;
+ all_ws();
+ consume(OTHER, "(") || error("Invalid operation");
+ ret["arguments"] = argument_list(store) || [];
+ all_ws();
+ consume(OTHER, ")") || error("Unterminated operation");
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated operation");
+ return ret;
+ };
+
+ var callback = function (store) {
+ all_ws(store, "pea");
+ var ret;
+ if (!consume(ID, "callback")) return;
+ all_ws();
+ var tok = consume(ID, "interface");
+ if (tok) {
+ tokens.unshift(tok);
+ ret = interface_();
+ ret.type = "callback interface";
+ return ret;
+ }
+ var name = consume(ID) || error("No name for callback");
+ ret = { type: "callback", name: name.value };
+ all_ws();
+ consume(OTHER, "=") || error("No assignment in callback");
+ all_ws();
+ ret.idlType = return_type();
+ all_ws();
+ consume(OTHER, "(") || error("No arguments in callback");
+ ret["arguments"] = argument_list(store) || [];
+ all_ws();
+ consume(OTHER, ")") || error("Unterminated callback");
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated callback");
+ return ret;
+ };
+
+ var attribute = function (store) {
+ all_ws(store, "pea");
+ var grabbed = []
+ , ret = {
+ type: "attribute"
+ , "static": false
+ , stringifier: false
+ , inherit: false
+ , readonly: false
+ };
+ if (consume(ID, "static")) {
+ ret["static"] = true;
+ grabbed.push(last_token);
+ }
+ else if (consume(ID, "stringifier")) {
+ ret.stringifier = true;
+ grabbed.push(last_token);
+ }
+ var w = all_ws();
+ if (w) grabbed.push(w);
+ if (consume(ID, "inherit")) {
+ if (ret["static"] || ret.stringifier) error("Cannot have a static or stringifier inherit");
+ ret.inherit = true;
+ grabbed.push(last_token);
+ var w = all_ws();
+ if (w) grabbed.push(w);
+ }
+ if (consume(ID, "readonly")) {
+ ret.readonly = true;
+ grabbed.push(last_token);
+ var w = all_ws();
+ if (w) grabbed.push(w);
+ }
+ if (!consume(ID, "attribute")) {
+ tokens = grabbed.concat(tokens);
+ return;
+ }
+ all_ws();
+ ret.idlType = type() || error("No type in attribute");
+ if (ret.idlType.sequence) error("Attributes cannot accept sequence types");
+ all_ws();
+ var name = consume(ID) || error("No name in attribute");
+ ret.name = name.value;
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated attribute");
+ return ret;
+ };
+
+ var return_type = function () {
+ var typ = type();
+ if (!typ) {
+ if (consume(ID, "void")) {
+ return "void";
+ }
+ else error("No return type");
+ }
+ return typ;
+ };
+
+ var operation = function (store) {
+ all_ws(store, "pea");
+ var ret = {
+ type: "operation"
+ , getter: false
+ , setter: false
+ , creator: false
+ , deleter: false
+ , legacycaller: false
+ , "static": false
+ , stringifier: false
+ };
+ while (true) {
+ all_ws();
+ if (consume(ID, "getter")) ret.getter = true;
+ else if (consume(ID, "setter")) ret.setter = true;
+ else if (consume(ID, "creator")) ret.creator = true;
+ else if (consume(ID, "deleter")) ret.deleter = true;
+ else if (consume(ID, "legacycaller")) ret.legacycaller = true;
+ else break;
+ }
+ if (ret.getter || ret.setter || ret.creator || ret.deleter || ret.legacycaller) {
+ all_ws();
+ ret.idlType = return_type();
+ operation_rest(ret, store);
+ return ret;
+ }
+ if (consume(ID, "static")) {
+ ret["static"] = true;
+ ret.idlType = return_type();
+ operation_rest(ret, store);
+ return ret;
+ }
+ else if (consume(ID, "stringifier")) {
+ ret.stringifier = true;-
+ all_ws();
+ if (consume(OTHER, ";")) return ret;
+ ret.idlType = return_type();
+ operation_rest(ret, store);
+ return ret;
+ }
+ ret.idlType = return_type();
+ all_ws();
+ if (consume(ID, "iterator")) {
+ all_ws();
+ ret.type = "iterator";
+ if (consume(ID, "object")) {
+ ret.iteratorObject = "object";
+ }
+ else if (consume(OTHER, "=")) {
+ all_ws();
+ var name = consume(ID) || error("No right hand side in iterator");
+ ret.iteratorObject = name.value;
+ }
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated iterator");
+ return ret;
+ }
+ else {
+ operation_rest(ret, store);
+ return ret;
+ }
+ };
+
+ var identifiers = function (arr) {
+ while (true) {
+ all_ws();
+ if (consume(OTHER, ",")) {
+ all_ws();
+ var name = consume(ID) || error("Trailing comma in identifiers list");
+ arr.push(name.value);
+ }
+ else break;
+ }
+ };
+
+ var serialiser = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "serializer")) return;
+ var ret = { type: "serializer" };
+ all_ws();
+ if (consume(OTHER, "=")) {
+ all_ws();
+ if (consume(OTHER, "{")) {
+ ret.patternMap = true;
+ all_ws();
+ var id = consume(ID);
+ if (id && id.value === "getter") {
+ ret.names = ["getter"];
+ }
+ else if (id && id.value === "inherit") {
+ ret.names = ["inherit"];
+ identifiers(ret.names);
+ }
+ else if (id) {
+ ret.names = [id.value];
+ identifiers(ret.names);
+ }
+ else {
+ ret.names = [];
+ }
+ all_ws();
+ consume(OTHER, "}") || error("Unterminated serializer pattern map");
+ }
+ else if (consume(OTHER, "[")) {
+ ret.patternList = true;
+ all_ws();
+ var id = consume(ID);
+ if (id && id.value === "getter") {
+ ret.names = ["getter"];
+ }
+ else if (id) {
+ ret.names = [id.value];
+ identifiers(ret.names);
+ }
+ else {
+ ret.names = [];
+ }
+ all_ws();
+ consume(OTHER, "]") || error("Unterminated serializer pattern list");
+ }
+ else {
+ var name = consume(ID) || error("Invalid serializer");
+ ret.name = name.value;
+ }
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated serializer");
+ return ret;
+ }
+ else if (consume(OTHER, ";")) {
+ // noop, just parsing
+ }
+ else {
+ ret.idlType = return_type();
+ all_ws();
+ ret.operation = operation_rest(null, store);
+ }
+ return ret;
+ };
+
+ var iterable_type = function() {
+ if (consume(ID, "iterable")) return "iterable";
+ else if (consume(ID, "legacyiterable")) return "legacyiterable";
+ else if (consume(ID, "maplike")) return "maplike";
+ else if (consume(ID, "setlike")) return "setlike";
+ else return;
+ }
+
+ var readonly_iterable_type = function() {
+ if (consume(ID, "maplike")) return "maplike";
+ else if (consume(ID, "setlike")) return "setlike";
+ else return;
+ }
+
+ var iterable = function (store) {
+ all_ws(store, "pea");
+ var grabbed = [],
+ ret = {type: null, idlType: null, readonly: false};
+ if (consume(ID, "readonly")) {
+ ret.readonly = true;
+ grabbed.push(last_token);
+ var w = all_ws();
+ if (w) grabbed.push(w);
+ }
+ var consumeItType = ret.readonly ? readonly_iterable_type : iterable_type;
+
+ var ittype = consumeItType();
+ if (!ittype) {
+ tokens = grabbed.concat(tokens);
+ return;
+ }
+
+ var secondTypeRequired = ittype === "maplike";
+ var secondTypeAllowed = secondTypeRequired || ittype === "iterable";
+ ret.type = ittype;
+ if (ret.type !== 'maplike' && ret.type !== 'setlike')
+ delete ret.readonly;
+ all_ws();
+ if (consume(OTHER, "<")) {
+ ret.idlType = type() || error("Error parsing " + ittype + " declaration");
+ all_ws();
+ if (secondTypeAllowed) {
+ var type2 = null;
+ if (consume(OTHER, ",")) {
+ all_ws();
+ type2 = type();
+ all_ws();
+ }
+ if (type2)
+ ret.idlType = [ret.idlType, type2];
+ else if (secondTypeRequired)
+ error("Missing second type argument in " + ittype + " declaration");
+ }
+ if (!consume(OTHER, ">")) error("Unterminated " + ittype + " declaration");
+ all_ws();
+ if (!consume(OTHER, ";")) error("Missing semicolon after " + ittype + " declaration");
+ }
+ else
+ error("Error parsing " + ittype + " declaration");
+
+ return ret;
+ }
+
+ var interface_ = function (isPartial, store) {
+ all_ws(isPartial ? null : store, "pea");
+ if (!consume(ID, "interface")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for interface");
+ var mems = []
+ , ret = {
+ type: "interface"
+ , name: name.value
+ , partial: false
+ , members: mems
+ };
+ if (!isPartial) ret.inheritance = inheritance() || null;
+ all_ws();
+ consume(OTHER, "{") || error("Bodyless interface");
+ while (true) {
+ all_ws(store ? mems : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("Missing semicolon after interface");
+ return ret;
+ }
+ var ea = extended_attrs(store ? mems : null);
+ all_ws();
+ var cnt = const_(store ? mems : null);
+ if (cnt) {
+ cnt.extAttrs = ea;
+ ret.members.push(cnt);
+ continue;
+ }
+ var mem = (opt.allowNestedTypedefs && typedef(store ? mems : null)) ||
+ iterable(store ? mems : null) ||
+ serialiser(store ? mems : null) ||
+ attribute(store ? mems : null) ||
+ operation(store ? mems : null) ||
+ error("Unknown member");
+ mem.extAttrs = ea;
+ ret.members.push(mem);
+ }
+ };
+
+ var partial = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "partial")) return;
+ var thing = dictionary(true, store) ||
+ interface_(true, store) ||
+ error("Partial doesn't apply to anything");
+ thing.partial = true;
+ return thing;
+ };
+
+ var dictionary = function (isPartial, store) {
+ all_ws(isPartial ? null : store, "pea");
+ if (!consume(ID, "dictionary")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for dictionary");
+ var mems = []
+ , ret = {
+ type: "dictionary"
+ , name: name.value
+ , partial: false
+ , members: mems
+ };
+ if (!isPartial) ret.inheritance = inheritance() || null;
+ all_ws();
+ consume(OTHER, "{") || error("Bodyless dictionary");
+ while (true) {
+ all_ws(store ? mems : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("Missing semicolon after dictionary");
+ return ret;
+ }
+ var ea = extended_attrs(store ? mems : null);
+ all_ws(store ? mems : null, "pea");
+ var required = consume(ID, "required");
+ var typ = type() || error("No type for dictionary member");
+ all_ws();
+ var name = consume(ID) || error("No name for dictionary member");
+ var dflt = default_();
+ if (required && dflt) error("Required member must not have a default");
+ ret.members.push({
+ type: "field"
+ , name: name.value
+ , required: !!required
+ , idlType: typ
+ , extAttrs: ea
+ , "default": dflt
+ });
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated dictionary member");
+ }
+ };
+
+ var exception = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "exception")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for exception");
+ var mems = []
+ , ret = {
+ type: "exception"
+ , name: name.value
+ , members: mems
+ };
+ ret.inheritance = inheritance() || null;
+ all_ws();
+ consume(OTHER, "{") || error("Bodyless exception");
+ while (true) {
+ all_ws(store ? mems : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("Missing semicolon after exception");
+ return ret;
+ }
+ var ea = extended_attrs(store ? mems : null);
+ all_ws(store ? mems : null, "pea");
+ var cnt = const_();
+ if (cnt) {
+ cnt.extAttrs = ea;
+ ret.members.push(cnt);
+ }
+ else {
+ var typ = type();
+ all_ws();
+ var name = consume(ID);
+ all_ws();
+ if (!typ || !name || !consume(OTHER, ";")) error("Unknown member in exception body");
+ ret.members.push({
+ type: "field"
+ , name: name.value
+ , idlType: typ
+ , extAttrs: ea
+ });
+ }
+ }
+ };
+
+ var enum_ = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "enum")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for enum");
+ var vals = []
+ , ret = {
+ type: "enum"
+ , name: name.value
+ , values: vals
+ };
+ all_ws();
+ consume(OTHER, "{") || error("No curly for enum");
+ var saw_comma = false;
+ while (true) {
+ all_ws(store ? vals : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("No semicolon after enum");
+ return ret;
+ }
+ var val = consume(STR) || error("Unexpected value in enum");
+ ret.values.push(val.value.replace(/"/g, ""));
+ all_ws(store ? vals : null);
+ if (consume(OTHER, ",")) {
+ if (store) vals.push({ type: "," });
+ all_ws(store ? vals : null);
+ saw_comma = true;
+ }
+ else {
+ saw_comma = false;
+ }
+ }
+ };
+
+ var typedef = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "typedef")) return;
+ var ret = {
+ type: "typedef"
+ };
+ all_ws();
+ ret.typeExtAttrs = extended_attrs();
+ all_ws(store, "tpea");
+ ret.idlType = type() || error("No type in typedef");
+ all_ws();
+ var name = consume(ID) || error("No name in typedef");
+ ret.name = name.value;
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated typedef");
+ return ret;
+ };
+
+ var implements_ = function (store) {
+ all_ws(store, "pea");
+ var target = consume(ID);
+ if (!target) return;
+ var w = all_ws();
+ if (consume(ID, "implements")) {
+ var ret = {
+ type: "implements"
+ , target: target.value
+ };
+ all_ws();
+ var imp = consume(ID) || error("Incomplete implements statement");
+ ret["implements"] = imp.value;
+ all_ws();
+ consume(OTHER, ";") || error("No terminating ; for implements statement");
+ return ret;
+ }
+ else {
+ // rollback
+ tokens.unshift(w);
+ tokens.unshift(target);
+ }
+ };
+
+ var definition = function (store) {
+ return callback(store) ||
+ interface_(false, store) ||
+ partial(store) ||
+ dictionary(false, store) ||
+ exception(store) ||
+ enum_(store) ||
+ typedef(store) ||
+ implements_(store)
+ ;
+ };
+
+ var definitions = function (store) {
+ if (!tokens.length) return [];
+ var defs = [];
+ while (true) {
+ var ea = extended_attrs(store ? defs : null)
+ , def = definition(store ? defs : null);
+ if (!def) {
+ if (ea.length) error("Stray extended attributes");
+ break;
+ }
+ def.extAttrs = ea;
+ defs.push(def);
+ }
+ return defs;
+ };
+ var res = definitions(opt.ws);
+ if (tokens.length) error("Unrecognised tokens");
+ return res;
+ };
+
+ var inNode = typeof module !== "undefined" && module.exports
+ , obj = {
+ parse: function (str, opt) {
+ if (!opt) opt = {};
+ var tokens = tokenise(str);
+ return parse(tokens, opt);
+ }
+ };
+
+ if (inNode) module.exports = obj;
+ else self.WebIDL2 = obj;
+}());
diff --git a/testing/web-platform/tests/resources/webidl2/lib/writer.js b/testing/web-platform/tests/resources/webidl2/lib/writer.js
new file mode 100644
index 000000000..ba8363738
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/lib/writer.js
@@ -0,0 +1,236 @@
+
+(function () {
+
+ var write = function (ast, opt) {
+ var curPea = ""
+ , curTPea = ""
+ , opt = opt || {}
+ , noop = function (str) { return str; }
+ , optNames = "type".split(" ")
+ , context = []
+ ;
+ for (var i = 0, n = optNames.length; i < n; i++) {
+ var o = optNames[i];
+ if (!opt[o]) opt[o] = noop;
+ }
+
+ var literal = function (it) {
+ return it.value;
+ };
+ var wsPea = function (it) {
+ curPea += it.value;
+ return "";
+ };
+ var wsTPea = function (it) {
+ curTPea += it.value;
+ return "";
+ };
+ var lineComment = function (it) {
+ return "//" + it.value + "\n";
+ };
+ var multilineComment = function (it) {
+ return "/*" + it.value + "*/";
+ };
+ var type = function (it) {
+ if (typeof it === "string") return opt.type(it); // XXX should maintain some context
+ if (it.union) return "(" + it.idlType.map(type).join(" or ") + ")";
+ var ret = "";
+ if (it.sequence) ret += "sequence<";
+ ret += type(it.idlType);
+ if (it.array) {
+ for (var i = 0, n = it.nullableArray.length; i < n; i++) {
+ var val = it.nullableArray[i];
+ if (val) ret += "?";
+ ret += "[]";
+ }
+ }
+ if (it.sequence) ret += ">";
+ if (it.nullable) ret += "?";
+
+ return ret;
+ };
+ var const_value = function (it) {
+ var tp = it. type;
+ if (tp === "boolean") return it.value ? "true" : "false";
+ else if (tp === "null") return "null";
+ else if (tp === "Infinity") return (it.negative ? "-" : "") + "Infinity";
+ else if (tp === "NaN") return "NaN";
+ else if (tp === "number") return it.value;
+ else return '"' + it.value + '"';
+ };
+ var argument = function (arg, pea) {
+ var ret = extended_attributes(arg.extAttrs, pea);
+ if (arg.optional) ret += "optional ";
+ ret += type(arg.idlType);
+ if (arg.variadic) ret += "...";
+ ret += " " + arg.name;
+ if (arg["default"]) ret += " = " + const_value(arg["default"]);
+ return ret;
+ };
+ var args = function (its) {
+ var res = ""
+ , pea = ""
+ ;
+ for (var i = 0, n = its.length; i < n; i++) {
+ var arg = its[i];
+ if (arg.type === "ws") res += arg.value;
+ else if (arg.type === "ws-pea") pea += arg.value;
+ else {
+ res += argument(arg, pea);
+ if (i < n - 1) res += ",";
+ pea = "";
+ }
+ }
+ return res;
+ };
+ var make_ext_at = function (it) {
+ if (it["arguments"] === null) return it.name;
+ context.unshift(it);
+ var ret = it.name + "(" + (it["arguments"].length ? args(it["arguments"]) : "") + ")";
+ context.shift(); // XXX need to add more contexts, but not more than needed for ReSpec
+ return ret;
+ };
+ var extended_attributes = function (eats, pea) {
+ if (!eats || !eats.length) return "";
+ return "[" + eats.map(make_ext_at).join(", ") + "]" + pea;
+ };
+
+ var modifiers = "getter setter creator deleter legacycaller stringifier static".split(" ");
+ var operation = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it.stringifier && !it.idlType) return "stringifier;";
+ for (var i = 0, n = modifiers.length; i < n; i++) {
+ var mod = modifiers[i];
+ if (it[mod]) ret += mod + " ";
+ }
+ ret += type(it.idlType) + " ";
+ if (it.name) ret += it.name;
+ ret += "(" + args(it["arguments"]) + ");";
+ return ret;
+ };
+
+ var attribute = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it["static"]) ret += "static ";
+ if (it.stringifier) ret += "stringifier ";
+ if (it.readonly) ret += "readonly ";
+ if (it.inherit) ret += "inherit ";
+ ret += "attribute " + type(it.idlType) + " " + it.name + ";";
+ return ret;
+ };
+
+ var interface_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it.partial) ret += "partial ";
+ ret += "interface " + it.name + " ";
+ if (it.inheritance) ret += ": " + it.inheritance + " ";
+ ret += "{" + iterate(it.members) + "};";
+ return ret;
+ };
+
+ var dictionary = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it.partial) ret += "partial ";
+ ret += "dictionary " + it.name + " ";
+ ret += "{" + iterate(it.members) + "};";
+ return ret;
+ };
+ var field = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += type(it.idlType) + " " + it.name;
+ if (it["default"]) ret += " = " + const_value(it["default"]);
+ ret += ";";
+ return ret;
+ };
+ var exception = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += "exception " + it.name + " ";
+ if (it.inheritance) ret += ": " + it.inheritance + " ";
+ ret += "{" + iterate(it.members) + "};";
+ return ret;
+ };
+ var const_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ return ret + "const " + type(it.idlType) + " " + it.name + " = " + const_value(it.value) + ";";
+ };
+ var typedef = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += "typedef " + extended_attributes(it.typeExtAttrs, curTPea);
+ curTPea = "";
+ return ret + type(it.idlType) + " " + it.name + ";";
+ };
+ var implements_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ return ret + it.target + " implements " + it["implements"] + ";";
+ };
+ var callback = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ return ret + "callback " + it.name + " = " + type(it.idlType) +
+ "(" + args(it["arguments"]) + ");";
+ };
+ var enum_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += "enum " + it.name + " {";
+ for (var i = 0, n = it.values.length; i < n; i++) {
+ var v = it.values[i];
+ if (typeof v === "string") ret += '"' + v + '"';
+ else if (v.type === "ws") ret += v.value;
+ else if (v.type === ",") ret += ",";
+ }
+ return ret + "};";
+ };
+
+ var table = {
+ ws: literal
+ , "ws-pea": wsPea
+ , "ws-tpea": wsTPea
+ , "line-comment": lineComment
+ , "multiline-comment": multilineComment
+ , "interface": interface_
+ , operation: operation
+ , attribute: attribute
+ , dictionary: dictionary
+ , field: field
+ , exception: exception
+ , "const": const_
+ , typedef: typedef
+ , "implements": implements_
+ , callback: callback
+ , "enum": enum_
+ };
+ var dispatch = function (it) {
+ return table[it.type](it);
+ };
+ var iterate = function (things) {
+ if (!things) return;
+ var ret = "";
+ for (var i = 0, n = things.length; i < n; i++) ret += dispatch(things[i]);
+ return ret;
+ };
+ return iterate(ast);
+ };
+
+
+ var inNode = typeof module !== "undefined" && module.exports
+ , obj = {
+ write: function (ast, opt) {
+ if (!opt) opt = {};
+ return write(ast, opt);
+ }
+ };
+
+ if (inNode) module.exports = obj;
+ else window.WebIDL2Writer = obj;
+
+}());
diff --git a/testing/web-platform/tests/resources/webidl2/package.json b/testing/web-platform/tests/resources/webidl2/package.json
new file mode 100644
index 000000000..c5ae7da2d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "webidl2",
+ "description": "A WebIDL Parser",
+ "version": "2.0.11",
+ "author": "Robin Berjon <robin@berjon.com>",
+ "license": "MIT",
+ "dependencies": {},
+ "devDependencies": {
+ "mocha": "2.2.5",
+ "expect.js": "0.3.1",
+ "underscore": "1.8.3",
+ "jsondiffpatch": "0.1.31",
+ "benchmark": "*",
+ "microtime": "1.4.2"
+ },
+ "scripts": {
+ "test": "mocha"
+ },
+ "repository": "git://github.com/darobin/webidl2.js",
+ "main": "index"
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid.js b/testing/web-platform/tests/resources/webidl2/test/invalid.js
new file mode 100644
index 000000000..c98218037
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid.js
@@ -0,0 +1,42 @@
+
+// NOTES:
+// - the errors actually still need to be reviewed to check that they
+// are fully correct interpretations of the IDLs
+
+var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2")
+, expect = require("expect.js")
+, pth = require("path")
+, fs = require("fs")
+;
+describe("Parses all of the invalid IDLs to check that they blow up correctly", function () {
+ var dir = pth.join(__dirname, "invalid/idl")
+ , skip = {}
+ , idls = fs.readdirSync(dir)
+ .filter(function (it) { return (/\.w?idl$/).test(it) && !skip[it]; })
+ .map(function (it) { return pth.join(dir, it); })
+ , errors = idls.map(function (it) { return pth.join(__dirname, "invalid", "json", pth.basename(it).replace(/\.w?idl/, ".json")); })
+ ;
+
+ for (var i = 0, n = idls.length; i < n; i++) {
+ var idl = idls[i], error = JSON.parse(fs.readFileSync(errors[i], "utf8"));
+ var func = (function (idl, err) {
+ return function () {
+ var error;
+ try {
+ var ast = wp.parse(fs.readFileSync(idl, "utf8"));
+ console.log(JSON.stringify(ast, null, 4));
+ }
+ catch (e) {
+ error = e;
+ }
+ finally {
+ expect(error).to.be.ok();
+ expect(error.message).to.equal(err.message);
+ expect(error.line).to.equal(err.line);
+ }
+
+ };
+ }(idl, error));
+ it("should produce the right error for " + idl, func);
+ }
+});
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/dict-required-default.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/dict-required-default.widl
new file mode 100644
index 000000000..412448d22
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/dict-required-default.widl
@@ -0,0 +1,5 @@
+// https://heycam.github.io/webidl/#required-dictionary-member
+// "A required dictionary member must not have a default value."
+dictionary Dict {
+ required long member = 0;
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/enum.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/enum.widl
new file mode 100644
index 000000000..c355c3251
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/enum.widl
@@ -0,0 +1 @@
+enum foo { 1, 2, 3}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/maplike-1type.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/maplike-1type.widl
new file mode 100644
index 000000000..33c274b8b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/maplike-1type.widl
@@ -0,0 +1,3 @@
+interface MapLikeOneType {
+ maplike<long>;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/module.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/module.widl
new file mode 100644
index 000000000..a4c79fdf1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/module.widl
@@ -0,0 +1,25 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+module gfx {
+
+ module geom {
+ interface Shape { /* ... */ };
+ interface Rectangle : Shape { /* ... */ };
+ interface Path : Shape { /* ... */ };
+ };
+
+ interface GraphicsContext {
+ void fillShape(geom::Shape s);
+ void strokeShape(geom::Shape s);
+ };
+};
+
+module gui {
+
+ interface Widget { /* ... */ };
+
+ interface Window : Widget {
+ gfx::GraphicsContext getGraphicsContext();
+ };
+
+ interface Button : Widget { /* ... */ };
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableany.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableany.widl
new file mode 100644
index 000000000..389576555
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableany.widl
@@ -0,0 +1,3 @@
+interface NonNullable {
+ attribute any? foo;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl
new file mode 100644
index 000000000..1deac5aee
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl
@@ -0,0 +1,5 @@
+interface Foo {};
+
+interface NonNullable {
+ attribute Foo?? foo;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/raises.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/raises.widl
new file mode 100644
index 000000000..ff65522f2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/raises.widl
@@ -0,0 +1,18 @@
+// getraises and setraises are not longer valid Web IDL
+interface Person {
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ attribute DOMString name setraises (InvalidName);
+
+ // An attribute whose value cannot be assigned to, and which can raise an
+ // exception some circumstances.
+ readonly attribute DOMString petName getraises (NoSuchPet);
+};
+
+exception SomeException {
+};
+
+interface ExceptionThrower {
+ // This attribute always throws a SomeException and never returns a value.
+ attribute long valueOf getraises(SomeException);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl
new file mode 100644
index 000000000..fc4ae2be9
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl
@@ -0,0 +1,3 @@
+interface ReadonlyIterable {
+ readonly iterable<long>;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/scopedname.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/scopedname.widl
new file mode 100644
index 000000000..cfcb1ccc9
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/scopedname.widl
@@ -0,0 +1,2 @@
+// scoped names are no longer valid in WebIDL
+ typedef gfx::geom::geom2d::Point Point;
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl
new file mode 100644
index 000000000..c23da82ac
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl
@@ -0,0 +1,3 @@
+interface sequenceAsAttribute {
+ attribute sequence<short> invalid;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/setlike-2types.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/setlike-2types.widl
new file mode 100644
index 000000000..1ecae22c0
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/setlike-2types.widl
@@ -0,0 +1,3 @@
+interface SetLikeTwoTypes {
+ setlike<long, long>;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/special-omittable.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/special-omittable.widl
new file mode 100644
index 000000000..bdfbfa709
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/special-omittable.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// omittable is no longer a recognized keywoard as of 20110905
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.idl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.idl
new file mode 100644
index 000000000..44fd3ff13
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.idl
@@ -0,0 +1,3 @@
+interface Util {
+ const DOMString hello = "world";
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/idl/typedef-nested.widl b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/typedef-nested.widl
new file mode 100644
index 000000000..106f30b8f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/typedef-nested.widl
@@ -0,0 +1,22 @@
+
+ interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+
+ interface Rect {
+ attribute Point topleft;
+ attribute Point bottomright;
+ };
+
+ interface Widget {
+ typedef sequence<Point> PointSequence;
+
+ readonly attribute Rect bounds;
+
+ boolean pointWithinBounds(Point p);
+ boolean allPointsWithinBounds(PointSequence ps);
+ };
+
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/dict-required-default.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/dict-required-default.json
new file mode 100644
index 000000000..c5afeca85
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/dict-required-default.json
@@ -0,0 +1,4 @@
+{
+ "message": "Required member must not have a default"
+, "line": 4
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/enum.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/enum.json
new file mode 100644
index 000000000..166115801
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/enum.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unexpected value in enum"
+, "line": 1
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/maplike-1type.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/maplike-1type.json
new file mode 100644
index 000000000..859a820a4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/maplike-1type.json
@@ -0,0 +1,4 @@
+{
+ "message": "Missing second type argument in maplike declaration",
+ "line": 2
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/module.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/module.json
new file mode 100644
index 000000000..3b0984d97
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/module.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unrecognised tokens"
+, "line": 2
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableany.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableany.json
new file mode 100644
index 000000000..cf5229e8e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableany.json
@@ -0,0 +1,4 @@
+{
+ "message": "Type any cannot be made nullable"
+, "line": 2
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableobjects.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableobjects.json
new file mode 100644
index 000000000..23cbb3e5d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableobjects.json
@@ -0,0 +1,4 @@
+{
+ "message": "Can't nullable more than once"
+, "line": 4
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/raises.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/raises.json
new file mode 100644
index 000000000..8b67afe4f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/raises.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unterminated attribute"
+, "line": 5
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/readonly-iterable.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/readonly-iterable.json
new file mode 100644
index 000000000..c6f52a246
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/readonly-iterable.json
@@ -0,0 +1,4 @@
+{
+ "message": "Invalid operation",
+ "line": 2
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/scopedname.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/scopedname.json
new file mode 100644
index 000000000..8e2cd8032
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/scopedname.json
@@ -0,0 +1,4 @@
+{
+ "message": "No name in typedef"
+, "line": 2
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json
new file mode 100644
index 000000000..b714f5d92
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json
@@ -0,0 +1,4 @@
+{
+ "message": "Attributes cannot accept sequence types"
+, "line": 2
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/setlike-2types.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/setlike-2types.json
new file mode 100644
index 000000000..c9e49b675
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/setlike-2types.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unterminated setlike declaration",
+ "line": 2
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/special-omittable.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/special-omittable.json
new file mode 100644
index 000000000..7acb08834
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/special-omittable.json
@@ -0,0 +1,4 @@
+{
+ "message": "Invalid operation"
+, "line": 6
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/stringconstants.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/stringconstants.json
new file mode 100644
index 000000000..d5bf1a883
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/stringconstants.json
@@ -0,0 +1,4 @@
+{
+ "message": "No value for const"
+, "line": 2
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/invalid/json/typedef-nested.json b/testing/web-platform/tests/resources/webidl2/test/invalid/json/typedef-nested.json
new file mode 100644
index 000000000..d7fb9182f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/typedef-nested.json
@@ -0,0 +1,4 @@
+{
+ "message": "Invalid operation"
+, "line": 14
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/mocha.opts b/testing/web-platform/tests/resources/webidl2/test/mocha.opts
new file mode 100644
index 000000000..5ada47be1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/mocha.opts
@@ -0,0 +1 @@
+--reporter spec
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax.js b/testing/web-platform/tests/resources/webidl2/test/syntax.js
new file mode 100644
index 000000000..712542a6b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax.js
@@ -0,0 +1,41 @@
+
+var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2")
+, expect = require("expect.js")
+, pth = require("path")
+, fs = require("fs")
+, jdp = require("jsondiffpatch")
+, debug = true
+;
+describe("Parses all of the IDLs to produce the correct ASTs", function () {
+ var dir = pth.join(__dirname, "syntax/idl")
+ , skip = {} // use if we have a broken test
+ , idls = fs.readdirSync(dir)
+ .filter(function (it) { return (/\.widl$/).test(it) && !skip[it]; })
+ .map(function (it) { return pth.join(dir, it); })
+ , jsons = idls.map(function (it) { return pth.join(__dirname, "syntax/json", pth.basename(it).replace(".widl", ".json")); })
+ ;
+
+ for (var i = 0, n = idls.length; i < n; i++) {
+ var idl = idls[i], json = jsons[i];
+
+ var func = (function (idl, json) {
+ return function () {
+ try {
+ var optFile = pth.join(__dirname, "syntax/opt", pth.basename(json));
+ var opt = undefined;
+ if (fs.existsSync(optFile))
+ opt = JSON.parse(fs.readFileSync(optFile, "utf8"));
+ var diff = jdp.diff(JSON.parse(fs.readFileSync(json, "utf8")),
+ wp.parse(fs.readFileSync(idl, "utf8"), opt));
+ if (diff && debug) console.log(JSON.stringify(diff, null, 4));
+ expect(diff).to.be(undefined);
+ }
+ catch (e) {
+ console.log(e.toString());
+ throw e;
+ }
+ };
+ }(idl, json));
+ it("should produce the same AST for " + idl, func);
+ }
+});
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/allowany.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/allowany.widl
new file mode 100644
index 000000000..2343bb963
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/allowany.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface B {
+ void g();
+ void g(B b);
+ void g([AllowAny] DOMString s);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/array.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/array.widl
new file mode 100644
index 000000000..22e21fb65
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/array.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/attributes.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/attributes.widl
new file mode 100644
index 000000000..7e1d691cb
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/attributes.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ // A simple attribute that can be set to any value the range an unsigned
+ // short can take.
+ attribute unsigned short age;
+
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/callback.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/callback.widl
new file mode 100644
index 000000000..adaf75e04
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/callback.widl
@@ -0,0 +1,7 @@
+callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+};
+
+callback SortCallback = boolean (any a, any b);
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/caller.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/caller.widl
new file mode 100644
index 000000000..92acb1c01
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/caller.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface NumberQuadrupler {
+ // This operation simply returns four times the given number x.
+ legacycaller float compute(float x);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/constants.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/constants.widl
new file mode 100644
index 000000000..5e28ae9c1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/constants.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/constructor.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/constructor.widl
new file mode 100644
index 000000000..f93ec08a6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/constructor.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl
new file mode 100644
index 000000000..48f8a0fdc
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl
@@ -0,0 +1,9 @@
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+dictionary WetPaintOptions : PaintOptions {
+ float hydrometry;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary.widl
new file mode 100644
index 000000000..c64a14c85
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/dictionary.widl
@@ -0,0 +1,15 @@
+// Extracted from Web IDL editors draft May 31 2011
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+ // https://heycam.github.io/webidl/#dfn-optional-argument-default-value allows sequences to default to "[]".
+ sequence<long> seq = [];
+ // https://heycam.github.io/webidl/#required-dictionary-member
+ required long reqSeq;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation-dos.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation-dos.widl
new file mode 100644
index 000000000..fb801101f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation-dos.widl
@@ -0,0 +1,33 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation.widl
new file mode 100644
index 000000000..003e9226f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/documentation.widl
@@ -0,0 +1,34 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+* <p><img src="foo.png" alt="Valid"/></p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/enum.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/enum.widl
new file mode 100644
index 000000000..37c4ffdde
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/enum.widl
@@ -0,0 +1,10 @@
+enum MealType { "rice", "noodles", "other" };
+
+interface Meal {
+ attribute MealType type;
+ attribute float size; // in grams
+
+ void initialize(MealType type, float size);
+};
+
+enum AltMealType { "rice", "noodles", "other", }; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl
new file mode 100644
index 000000000..6b3e0eda2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl
new file mode 100644
index 000000000..258fdeba6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl
@@ -0,0 +1,7 @@
+// from http://lists.w3.org/Archives/Public/public-script-coord/2010OctDec/0112.html
+ exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : DOMException { };
+ exception NoModificationAllowedError : DOMException { }; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception.widl
new file mode 100644
index 000000000..f4b6ae29e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/exception.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl
new file mode 100644
index 000000000..f769c2559
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl
@@ -0,0 +1,6 @@
+// Extracted from http://www.w3.org/TR/2015/WD-service-workers-20150205/
+
+[Global=(Worker,ServiceWorker), Exposed=ServiceWorker]
+interface ServiceWorkerGlobalScope : WorkerGlobalScope {
+
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/generic.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/generic.widl
new file mode 100644
index 000000000..02b64572a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/generic.widl
@@ -0,0 +1,17 @@
+interface Foo {
+ Promise<ResponsePromise<sequence<DOMString?>>> bar();
+ readonly attribute Promise<DOMString>[] baz;
+};
+
+// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-08
+
+interface ServiceWorkerClients {
+ Promise<Client[]?> getServiced();
+ Promise<any> reloadAll();
+};
+
+// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-13
+
+interface FetchEvent : Event {
+ ResponsePromise<any> default();
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/getter-setter.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/getter-setter.widl
new file mode 100644
index 000000000..bdf87e1c7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/getter-setter.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl
new file mode 100644
index 000000000..33893d4c6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl
@@ -0,0 +1,44 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ // Typedef identifier: "number"
+ // Qualified name: "::framework::number"
+ typedef float number;
+
+ // Exception identifier: "FrameworkException"
+ // Qualified name: "::framework::FrameworkException"
+ exception FrameworkException {
+
+ // Constant identifier: "ERR_NOT_FOUND"
+ // Qualified name: "::framework::FrameworkException::ERR_NOT_FOUND"
+ const long ERR_NOT_FOUND = 1;
+
+ // Exception field identifier: "code"
+ long code;
+ };
+
+ // Interface identifier: "System"
+ // Qualified name: "::framework::System"
+ interface System {
+
+ // Operation identifier: "createObject"
+ // Operation argument identifier: "interface"
+ object createObject(DOMString _interface);
+
+ // Operation has no identifier; it declares a getter.
+ getter DOMString (DOMString keyName);
+ };
+
+
+ // Interface identifier: "TextField"
+ // Qualified name: "::framework::gui::TextField"
+ interface TextField {
+
+ // Attribute identifier: "const"
+ attribute boolean _const;
+
+ // Attribute identifier: "value"
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/implements.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/implements.widl
new file mode 100644
index 000000000..7a310926f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/implements.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Node {
+ readonly attribute unsigned short nodeType;
+ // ...
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ EventListener listener,
+ boolean useCapture);
+ // ...
+ };
+
+ Node implements EventTarget;
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/indexed-properties.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/indexed-properties.widl
new file mode 100644
index 000000000..acf0ed3bf
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/indexed-properties.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/inherits-getter.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/inherits-getter.widl
new file mode 100644
index 000000000..558e81164
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/inherits-getter.widl
@@ -0,0 +1,16 @@
+interface Animal {
+
+ // A simple attribute that can be set to any string value.
+ readonly attribute DOMString name;
+};
+
+interface Person : Animal {
+
+ // An attribute whose value cannot be assigned to.
+ readonly attribute unsigned short age;
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ // Its getter behavior is inherited from Animal, and need not be specified
+ // the description of Person.
+ inherit attribute DOMString name;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/interface-inherits.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/interface-inherits.widl
new file mode 100644
index 000000000..7921def77
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/interface-inherits.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : Animal {
+ attribute Dog pet;
+};
+
+interface Dog : Animal {
+ attribute Human owner;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterable.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterable.widl
new file mode 100644
index 000000000..c7dfafa4d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterable.widl
@@ -0,0 +1,7 @@
+interface IterableOne {
+ iterable<long>;
+};
+
+interface IterableTwo {
+ iterable<short, double?>;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterator.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterator.widl
new file mode 100644
index 000000000..3bf1b36de
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterator.widl
@@ -0,0 +1,35 @@
+interface SessionManager {
+ Session getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionManager2 {
+ Session2 getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session2 iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ Node iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ Node iterator object;
+ }; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/legacyiterable.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/legacyiterable.widl
new file mode 100644
index 000000000..eafa7cf04
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/legacyiterable.widl
@@ -0,0 +1,3 @@
+interface LegacyIterable {
+ legacyiterable<long>;
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/map.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/map.widl
new file mode 100644
index 000000000..19b54f80a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/map.widl
@@ -0,0 +1,5 @@
+// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-06
+
+[MapClass(DOMString, DOMString)]
+interface HeaderMap {
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/maplike.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/maplike.widl
new file mode 100644
index 000000000..7b79b3888
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/maplike.widl
@@ -0,0 +1,7 @@
+interface MapLike {
+ maplike<long, float>;
+};
+
+interface ReadOnlyMapLike {
+ readonly maplike<long, float>;
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/namedconstructor.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/namedconstructor.widl
new file mode 100644
index 000000000..c468b78f8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/namedconstructor.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : HTMLMediaElement {
+ // ...
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl
new file mode 100644
index 000000000..c17d75ff8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullable.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullable.widl
new file mode 100644
index 000000000..ccbf625ff
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullable.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+ // ...
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullableobjects.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullableobjects.widl
new file mode 100644
index 000000000..83d1d40b2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/nullableobjects.widl
@@ -0,0 +1,13 @@
+// Extracted from WebIDL spec 2011-05-23
+
+interface A {
+ // ...
+};
+interface B {
+ // ...
+};
+interface C {
+ void f(A? x);
+ void f(B? x);
+
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl
new file mode 100644
index 000000000..379053b45
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl
@@ -0,0 +1,4 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/overloading.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/overloading.widl
new file mode 100644
index 000000000..ef1288a88
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/overloading.widl
@@ -0,0 +1,20 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ // ...
+};
+
+interface B {
+ // ...
+};
+
+interface C {
+ void f(A x);
+ void f(B x);
+};
+
+interface A {
+ /* f1 */ void f(DOMString a);
+ /* f2 */ void f([AllowAny] DOMString a, DOMString b, float... c);
+ /* f3 */ void f();
+ /* f4 */ void f(long a, DOMString b, optional DOMString c, float... d);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl
new file mode 100644
index 000000000..79211c29e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/partial-interface.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/partial-interface.widl
new file mode 100644
index 000000000..90e7e0ea4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/partial-interface.widl
@@ -0,0 +1,7 @@
+interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/primitives.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/primitives.widl
new file mode 100644
index 000000000..92939601a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/primitives.widl
@@ -0,0 +1,19 @@
+interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/prototyperoot.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/prototyperoot.widl
new file mode 100644
index 000000000..30dd5cbca
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/prototyperoot.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/putforwards.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/putforwards.widl
new file mode 100644
index 000000000..1e50a4ee3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/putforwards.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Person {
+ [PutForwards=full] readonly attribute Name name;
+ attribute unsigned short age;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/reg-operations.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/reg-operations.widl
new file mode 100644
index 000000000..13997cb1d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/reg-operations.widl
@@ -0,0 +1,17 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ // An operation that takes no arguments, returns a boolean
+ boolean isMouseOver();
+
+ // Overloaded operations.
+ void setDimensions(Dimensions size);
+ void setDimensions(unsigned long width, unsigned long height);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/replaceable.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/replaceable.widl
new file mode 100644
index 000000000..c14d0c376
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/replaceable.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/sequence.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/sequence.widl
new file mode 100644
index 000000000..6ba0d390d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/sequence.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// edited to remove sequence as attributes, now invalid
+interface Canvas {
+ void drawPolygon(sequence<float> coordinates);
+ sequence<float> getInflectionPoints();
+ // ...
+};
+
+// Make sure sequence can still be registered as a type.
+interface Foo {
+ sequence bar();
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/serializer.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/serializer.widl
new file mode 100644
index 000000000..6f6ccd0e8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/serializer.widl
@@ -0,0 +1,64 @@
+interface Transaction {
+ readonly attribute Account from;
+ readonly attribute Account to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute Account2 from;
+ readonly attribute Account2 to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/setlike.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/setlike.widl
new file mode 100644
index 000000000..890e8e5a7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/setlike.widl
@@ -0,0 +1,7 @@
+interface SetLike {
+ setlike<long>;
+};
+
+interface ReadOnlySetLike {
+ readonly setlike<long>;
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/static.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/static.widl
new file mode 100644
index 000000000..5b2cd3659
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/static.widl
@@ -0,0 +1,11 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Point { /* ... */ };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static Point triangulate(Circle c1, Circle c2, Circle c3);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl
new file mode 100644
index 000000000..c964ecb93
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl
new file mode 100644
index 000000000..b5d7c87e7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier.widl
new file mode 100644
index 000000000..4eb483d9b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/stringifier.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasnull.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasnull.widl
new file mode 100644
index 000000000..d3c55b008
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasnull.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasundefined.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasundefined.widl
new file mode 100644
index 000000000..e30050f84
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/treatasundefined.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-nested.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-nested.widl
new file mode 100644
index 000000000..106f30b8f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-nested.widl
@@ -0,0 +1,22 @@
+
+ interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+
+ interface Rect {
+ attribute Point topleft;
+ attribute Point bottomright;
+ };
+
+ interface Widget {
+ typedef sequence<Point> PointSequence;
+
+ readonly attribute Rect bounds;
+
+ boolean pointWithinBounds(Point p);
+ boolean allPointsWithinBounds(PointSequence ps);
+ };
+
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef.widl
new file mode 100644
index 000000000..b4c17d8d3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef.widl
@@ -0,0 +1,22 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence<Point> PointSequence;
+
+ interface Rect {
+ attribute Point topleft;
+ attribute Point bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute Rect bounds;
+
+ boolean pointWithinBounds(Point p);
+ boolean allPointsWithinBounds(PointSequence ps);
+ };
+
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typesuffixes.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typesuffixes.widl
new file mode 100644
index 000000000..95e31c169
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/typesuffixes.widl
@@ -0,0 +1,3 @@
+interface Suffixes {
+ void test(sequence<DOMString[]?>? foo);
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl
new file mode 100644
index 000000000..4d99f0196
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/uniontype.widl
@@ -0,0 +1,3 @@
+interface Union {
+ attribute (float or (Date or Event) or (Node or DOMString)?) test;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/idl/variadic-operations.widl b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/variadic-operations.widl
new file mode 100644
index 000000000..51fae4cc1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/idl/variadic-operations.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/allowany.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/allowany.json
new file mode 100644
index 000000000..8abc7f9e0
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/allowany.json
@@ -0,0 +1,109 @@
+[
+ {
+ "type": "interface",
+ "name": "B",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "g",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "g",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "B"
+ },
+ "name": "b"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "g",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "AllowAny",
+ "arguments": null
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "s"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/array.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/array.json
new file mode 100644
index 000000000..39afaf6c8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/array.json
@@ -0,0 +1,34 @@
+[
+ {
+ "type": "interface",
+ "name": "LotteryResults",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": 2,
+ "nullableArray": [false, false],
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "numbers",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/attributes.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/attributes.json
new file mode 100644
index 000000000..cdf46b0ec
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/attributes.json
@@ -0,0 +1,56 @@
+[
+ {
+ "type": "exception",
+ "name": "InvalidName",
+ "members": [
+ {
+ "type": "field",
+ "name": "reason",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "NoSuchPet",
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Person",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "age",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/callback.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/callback.json
new file mode 100644
index 000000000..43a517510
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/callback.json
@@ -0,0 +1,119 @@
+[
+ {
+ "type": "callback",
+ "name": "AsyncOperationCallback",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "status"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "callback interface",
+ "name": "EventHandler",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "eventOccurred",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "details"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "callback",
+ "name": "SortCallback",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "a"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "b"
+ }
+ ],
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/caller.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/caller.json
new file mode 100644
index 000000000..a0fb5e396
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/caller.json
@@ -0,0 +1,47 @@
+[
+ {
+ "type": "interface",
+ "name": "NumberQuadrupler",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": true,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "compute",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/constants.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/constants.json
new file mode 100644
index 000000000..0fe6e92af
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/constants.json
@@ -0,0 +1,141 @@
+[
+ {
+ "type": "interface",
+ "name": "Util",
+ "partial": false,
+ "members": [
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "boolean",
+ "name": "DEBUG",
+ "value": {
+ "type": "boolean",
+ "value": false
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "negative",
+ "value": {
+ "type": "number",
+ "value": -1
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "octet",
+ "name": "LF",
+ "value": {
+ "type": "number",
+ "value": 10
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "unsigned long",
+ "name": "BIT_MASK",
+ "value": {
+ "type": "number",
+ "value": 64512
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "float",
+ "name": "AVOGADRO",
+ "value": {
+ "type": "number",
+ "value": 6.022e+23
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "unrestricted float",
+ "name": "sobig",
+ "value": {
+ "type": "Infinity",
+ "negative": false
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "unrestricted double",
+ "name": "minusonedividedbyzero",
+ "value": {
+ "type": "Infinity",
+ "negative": true
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "notanumber",
+ "value": {
+ "type": "NaN"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "Error",
+ "members": [
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "ERR_UNKNOWN",
+ "value": {
+ "type": "number",
+ "value": 0
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "ERR_OUT_OF_MEMORY",
+ "value": {
+ "type": "number",
+ "value": 1
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "field",
+ "name": "errorCode",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "short"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/constructor.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/constructor.json
new file mode 100644
index 000000000..e5944f32e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/constructor.json
@@ -0,0 +1,103 @@
+[
+ {
+ "type": "interface",
+ "name": "Circle",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "r",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cx",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cy",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "circumference",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ },
+ {
+ "name": "Constructor",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "radius"
+ }
+ ]
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary-inherits.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
new file mode 100644
index 000000000..fbb2338a8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
@@ -0,0 +1,83 @@
+[
+ {
+ "type": "dictionary",
+ "name": "PaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "fillPattern",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "string",
+ "value": "black"
+ }
+ },
+ {
+ "type": "field",
+ "name": "strokePattern",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "null"
+ }
+ },
+ {
+ "type": "field",
+ "name": "position",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "dictionary",
+ "name": "WetPaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "hydrometry",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "PaintOptions",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary.json
new file mode 100644
index 000000000..a7c89caab
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary.json
@@ -0,0 +1,135 @@
+[
+ {
+ "type": "dictionary",
+ "name": "PaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "fillPattern",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "string",
+ "value": "black"
+ }
+ },
+ {
+ "type": "field",
+ "name": "strokePattern",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "null"
+ }
+ },
+ {
+ "type": "field",
+ "name": "position",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "field",
+ "name": "seq",
+ "required": false,
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ }
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "sequence",
+ "value": []
+ }
+ },
+ {
+ "type": "field",
+ "name": "reqSeq",
+ "required": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "dictionary",
+ "name": "A",
+ "partial": true,
+ "members": [
+ {
+ "type": "field",
+ "name": "h",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "field",
+ "name": "d",
+ "required": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ }
+ ],
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation-dos.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation-dos.json
new file mode 100644
index 000000000..340e039b4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation-dos.json
@@ -0,0 +1,10 @@
+[
+ {
+ "type": "interface",
+ "name": "Documentation",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation.json
new file mode 100644
index 000000000..340e039b4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation.json
@@ -0,0 +1,10 @@
+[
+ {
+ "type": "interface",
+ "name": "Documentation",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/enum.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/enum.json
new file mode 100644
index 000000000..196ee4e64
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/enum.json
@@ -0,0 +1,115 @@
+[
+ {
+ "type": "enum",
+ "name": "MealType",
+ "values": [
+ "rice",
+ "noodles",
+ "other"
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Meal",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "MealType"
+ },
+ "name": "type",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "size",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "initialize",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "MealType"
+ },
+ "name": "type"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "size"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "enum",
+ "name": "AltMealType",
+ "values": [
+ "rice",
+ "noodles",
+ "other"
+ ],
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/equivalent-decl.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/equivalent-decl.json
new file mode 100644
index 000000000..55a787fdc
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/equivalent-decl.json
@@ -0,0 +1,312 @@
+[
+ {
+ "type": "interface",
+ "name": "Dictionary",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "propertyCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "getProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Dictionary",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "propertyCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "getProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/exception-inheritance.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/exception-inheritance.json
new file mode 100644
index 000000000..f4dc68699
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/exception-inheritance.json
@@ -0,0 +1,37 @@
+[
+ {
+ "type": "exception",
+ "name": "DOMException",
+ "members": [
+ {
+ "type": "field",
+ "name": "code",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "HierarchyRequestError",
+ "members": [],
+ "inheritance": "DOMException",
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "NoModificationAllowedError",
+ "members": [],
+ "inheritance": "DOMException",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/exception.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/exception.json
new file mode 100644
index 000000000..3f16de828
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/exception.json
@@ -0,0 +1,35 @@
+[
+ {
+ "type": "interface",
+ "name": "Dahut",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "type",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "SomeException",
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json
new file mode 100644
index 000000000..228c4b824
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json
@@ -0,0 +1,30 @@
+[
+ {
+ "type": "interface",
+ "name": "ServiceWorkerGlobalScope",
+ "partial": false,
+ "members": [],
+ "inheritance": "WorkerGlobalScope",
+ "extAttrs": [
+ {
+ "name": "Global",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier-list",
+ "value": [
+ "Worker",
+ "ServiceWorker"
+ ]
+ }
+ },
+ {
+ "name": "Exposed",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "ServiceWorker"
+ }
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/generic.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/generic.json
new file mode 100644
index 000000000..e39654ffd
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/generic.json
@@ -0,0 +1,181 @@
+[
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "Promise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "ResponsePromise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ }
+ }
+ }
+ },
+ "name": "bar",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": "Promise",
+ "nullable": false,
+ "array": 1,
+ "nullableArray": [false],
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ }
+ },
+ "name": "baz",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "ServiceWorkerClients",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "Promise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "nullableArray": [false],
+ "array": 1,
+ "union": false,
+ "idlType": "Client"
+ }
+ },
+ "name": "getServiced",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "Promise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ }
+ },
+ "name": "reloadAll",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "FetchEvent",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "ResponsePromise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ }
+ },
+ "name": "default",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Event",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/getter-setter.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/getter-setter.json
new file mode 100644
index 000000000..94d20d594
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/getter-setter.json
@@ -0,0 +1,114 @@
+[
+ {
+ "type": "interface",
+ "name": "Dictionary",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "propertyCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
new file mode 100644
index 000000000..a91f8c8eb
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
@@ -0,0 +1,217 @@
+[
+ {
+ "type": "typedef",
+ "typeExtAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "FrameworkException",
+ "members": [
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "long",
+ "name": "ERR_NOT_FOUND",
+ "value": {
+ "type": "number",
+ "value": 1
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "field",
+ "name": "code",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "System",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "createObject",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "interface"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "keyName"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "TextField",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "const",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "value",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "op",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "interface"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/implements.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/implements.json
new file mode 100644
index 000000000..fa00e3374
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/implements.json
@@ -0,0 +1,107 @@
+[
+ {
+ "type": "interface",
+ "name": "Node",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "nodeType",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "EventTarget",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "addEventListener",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "type"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "EventListener"
+ },
+ "name": "listener"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "useCapture"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "implements",
+ "target": "Node",
+ "implements": "EventTarget",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/indexed-properties.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/indexed-properties.json
new file mode 100644
index 000000000..23cc4ab10
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/indexed-properties.json
@@ -0,0 +1,272 @@
+[
+ {
+ "type": "interface",
+ "name": "OrderedMap",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "size",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "getByIndex",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setByIndex",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "value"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": true,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "removeByIndex",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "get",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": true,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "set",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "value"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": true,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "remove",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/inherits-getter.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/inherits-getter.json
new file mode 100644
index 000000000..468e3caef
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/inherits-getter.json
@@ -0,0 +1,71 @@
+[
+ {
+ "type": "interface",
+ "name": "Animal",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Person",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "age",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": true,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Animal",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/interface-inherits.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/interface-inherits.json
new file mode 100644
index 000000000..eee07cd1d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/interface-inherits.json
@@ -0,0 +1,80 @@
+[
+ {
+ "type": "interface",
+ "name": "Animal",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Human",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Dog"
+ },
+ "name": "pet",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Animal",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Dog",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Human"
+ },
+ "name": "owner",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Animal",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterable.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterable.json
new file mode 100644
index 000000000..3e38991dd
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterable.json
@@ -0,0 +1,55 @@
+[
+ {
+ "type": "interface",
+ "name": "IterableOne",
+ "partial": false,
+ "members": [
+ {
+ "type": "iterable",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "IterableTwo",
+ "partial": false,
+ "members": [
+ {
+ "type": "iterable",
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "short"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "double"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+]
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterator.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterator.json
new file mode 100644
index 000000000..cc3c9ec50
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterator.json
@@ -0,0 +1,301 @@
+[
+ {
+ "type": "interface",
+ "name": "SessionManager",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session"
+ },
+ "name": "getSessionForUser",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "sessionCount",
+ "extAttrs": []
+ },
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Session",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "SessionManager2",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session2"
+ },
+ "name": "getSessionForUser",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "sessionCount",
+ "extAttrs": []
+ },
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session2"
+ },
+ "iteratorObject": "SessionIterator",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Session2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "SessionIterator",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "remainingSessions",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "NodeList",
+ "partial": false,
+ "members": [
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Node"
+ },
+ "iteratorObject": "NodeIterator",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "NodeIterator",
+ "partial": false,
+ "members": [
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Node"
+ },
+ "iteratorObject": "object",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/legacyiterable.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/legacyiterable.json
new file mode 100644
index 000000000..e63f99de4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/legacyiterable.json
@@ -0,0 +1,24 @@
+[
+ {
+ "type": "interface",
+ "name": "LegacyIterable",
+ "partial": false,
+ "members": [
+ {
+ "type": "legacyiterable",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+]
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/map.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/map.json
new file mode 100644
index 000000000..03ce9412e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/map.json
@@ -0,0 +1,29 @@
+[
+ {
+ "type": "interface",
+ "name": "HeaderMap",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": [{
+ "name": "MapClass",
+ "arguments": null,
+ "typePair": [{
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ }]
+ }]
+ }
+]
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/maplike.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/maplike.json
new file mode 100644
index 000000000..017d8b3f3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/maplike.json
@@ -0,0 +1,67 @@
+[
+ {
+ "type": "interface",
+ "name": "MapLike",
+ "partial": false,
+ "members": [
+ {
+ "type": "maplike",
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ }
+ ],
+ "readonly": false,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "ReadOnlyMapLike",
+ "partial": false,
+ "members": [
+ {
+ "type": "maplike",
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ }
+ ],
+ "readonly": true,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+]
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/namedconstructor.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/namedconstructor.json
new file mode 100644
index 000000000..a947a64a4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/namedconstructor.json
@@ -0,0 +1,42 @@
+[
+ {
+ "type": "interface",
+ "name": "HTMLAudioElement",
+ "partial": false,
+ "members": [],
+ "inheritance": "HTMLMediaElement",
+ "extAttrs": [
+ {
+ "name": "NamedConstructor",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "Audio"
+ }
+ },
+ {
+ "name": "NamedConstructor",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "src"
+ }
+ ],
+ "rhs": {
+ "type": "identifier",
+ "value": "Audio"
+ }
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/nointerfaceobject.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
new file mode 100644
index 000000000..90f0d63c8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
@@ -0,0 +1,52 @@
+[
+ {
+ "type": "interface",
+ "name": "Query",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "lookupEntry",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "key"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "NoInterfaceObject",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullable.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullable.json
new file mode 100644
index 000000000..300442f0d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullable.json
@@ -0,0 +1,48 @@
+[
+ {
+ "type": "interface",
+ "name": "MyConstants",
+ "partial": false,
+ "members": [
+ {
+ "type": "const",
+ "nullable": true,
+ "idlType": "boolean",
+ "name": "ARE_WE_THERE_YET",
+ "value": {
+ "type": "boolean",
+ "value": false
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Node",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "namespaceURI",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullableobjects.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullableobjects.json
new file mode 100644
index 000000000..40f7db0c1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullableobjects.json
@@ -0,0 +1,99 @@
+[
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "B",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "C",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "A"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "B"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/operation-optional-arg.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
new file mode 100644
index 000000000..6ca32576b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
@@ -0,0 +1,93 @@
+[
+ {
+ "type": "interface",
+ "name": "ColorCreator",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "createColor",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "v1"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "v2"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "v3"
+ },
+ {
+ "optional": true,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "alpha",
+ "default": {
+ "type": "number",
+ "value": 3.5
+ }
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/overloading.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/overloading.json
new file mode 100644
index 000000000..c3baa4396
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/overloading.json
@@ -0,0 +1,312 @@
+[
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "B",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "C",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "A"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "B"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "a"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "AllowAny",
+ "arguments": null
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "a"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "b"
+ },
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "c"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "a"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "b"
+ },
+ {
+ "optional": true,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "c"
+ },
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "d"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/overridebuiltins.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/overridebuiltins.json
new file mode 100644
index 000000000..9e2f795e2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/overridebuiltins.json
@@ -0,0 +1,69 @@
+[
+ {
+ "type": "interface",
+ "name": "StringMap2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "length",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "lookup",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "key"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "OverrideBuiltins",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/partial-interface.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/partial-interface.json
new file mode 100644
index 000000000..53c65a453
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/partial-interface.json
@@ -0,0 +1,53 @@
+[
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "bar",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": true,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "quux",
+ "extAttrs": []
+ }
+ ],
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/primitives.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/primitives.json
new file mode 100644
index 000000000..7160c2a4c
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/primitives.json
@@ -0,0 +1,300 @@
+[
+ {
+ "type": "interface",
+ "name": "Primitives",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "truth",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "byte"
+ },
+ "name": "character",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "octet"
+ },
+ "name": "value",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "short"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "positive",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "big",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "bigpositive",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long long"
+ },
+ "name": "bigbig",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long long"
+ },
+ "name": "bigbigpositive",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "real",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "double"
+ },
+ "name": "bigreal",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unrestricted float"
+ },
+ "name": "realwithinfinity",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unrestricted double"
+ },
+ "name": "bigrealwithinfinity",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "string",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "ByteString"
+ },
+ "name": "bytes",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Date"
+ },
+ "name": "date",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "RegExp"
+ },
+ "name": "regexp",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/prototyperoot.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/prototyperoot.json
new file mode 100644
index 000000000..666798d94
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/prototyperoot.json
@@ -0,0 +1,33 @@
+[
+ {
+ "type": "interface",
+ "name": "Node",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "nodeType",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "PrototypeRoot",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/putforwards.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/putforwards.json
new file mode 100644
index 000000000..bd5e619ca
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/putforwards.json
@@ -0,0 +1,54 @@
+[
+ {
+ "type": "interface",
+ "name": "Person",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Name"
+ },
+ "name": "name",
+ "extAttrs": [
+ {
+ "name": "PutForwards",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "full"
+ }
+ }
+ ]
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "age",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/reg-operations.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/reg-operations.json
new file mode 100644
index 000000000..c827fff03
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/reg-operations.json
@@ -0,0 +1,168 @@
+[
+ {
+ "type": "interface",
+ "name": "Dimensions",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "width",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "height",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "NoPointerDevice",
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Button",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "isMouseOver",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setDimensions",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Dimensions"
+ },
+ "name": "size"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setDimensions",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "width"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "height"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/replaceable.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/replaceable.json
new file mode 100644
index 000000000..4d25f3d93
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/replaceable.json
@@ -0,0 +1,54 @@
+[
+ {
+ "type": "interface",
+ "name": "Counter",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "value",
+ "extAttrs": [
+ {
+ "name": "Replaceable",
+ "arguments": null
+ }
+ ]
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "increment",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/sequence.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/sequence.json
new file mode 100644
index 000000000..7ddd402b4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/sequence.json
@@ -0,0 +1,113 @@
+[
+ {
+ "type": "interface",
+ "name": "Canvas",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "drawPolygon",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ }
+ },
+ "name": "coordinates"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ }
+ },
+ "name": "getInflectionPoints",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "sequence"
+ },
+ "name": "bar",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/serializer.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/serializer.json
new file mode 100644
index 000000000..79b501fcb
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/serializer.json
@@ -0,0 +1,591 @@
+[
+ {
+ "type": "interface",
+ "name": "Transaction",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account"
+ },
+ "name": "from",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account"
+ },
+ "name": "to",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "amount",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "description",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "operation": {
+ "name": "serialize",
+ "arguments": []
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Transaction2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account2"
+ },
+ "name": "from",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account2"
+ },
+ "name": "to",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "amount",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "description",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "from",
+ "to",
+ "amount",
+ "description"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "name": "number",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account3",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "attribute"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account4",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "getItem",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "getter"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account5",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "secondname",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "inherit",
+ "secondname"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Account",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account6",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "secondname",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "inherit",
+ "attribute"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Account",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account7",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternList": true,
+ "names": [
+ "name",
+ "number"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account8",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "getItem",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternList": true,
+ "names": [
+ "getter"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/setlike.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/setlike.json
new file mode 100644
index 000000000..d44043a94
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/setlike.json
@@ -0,0 +1,47 @@
+[
+ {
+ "type": "interface",
+ "name": "SetLike",
+ "partial": false,
+ "members": [
+ {
+ "type": "setlike",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "readonly": false,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "ReadOnlySetLike",
+ "partial": false,
+ "members": [
+ {
+ "type": "setlike",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "readonly": true,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+]
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/static.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/static.json
new file mode 100644
index 000000000..faab12b29
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/static.json
@@ -0,0 +1,151 @@
+[
+ {
+ "type": "interface",
+ "name": "Point",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Circle",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cx",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cy",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "radius",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": true,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "triangulationCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": true,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "triangulate",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Circle"
+ },
+ "name": "c1"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Circle"
+ },
+ "name": "c2"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Circle"
+ },
+ "name": "c3"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-attribute.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
new file mode 100644
index 000000000..196ee6f1a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
@@ -0,0 +1,50 @@
+[
+ {
+ "type": "interface",
+ "name": "Student",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "id",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": true,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-custom.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-custom.json
new file mode 100644
index 000000000..b4ab7392e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-custom.json
@@ -0,0 +1,88 @@
+[
+ {
+ "type": "interface",
+ "name": "Student",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "id",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "familyName",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "givenName",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": null,
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier.json
new file mode 100644
index 000000000..ad3abde85
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier.json
@@ -0,0 +1,52 @@
+[
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": null,
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": true,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasnull.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasnull.json
new file mode 100644
index 000000000..8bacb967a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasnull.json
@@ -0,0 +1,90 @@
+[
+ {
+ "type": "interface",
+ "name": "Dog",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "owner",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "isMemberOfBreed",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "TreatNullAs",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "EmptyString"
+ }
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "breedName"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasundefined.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasundefined.json
new file mode 100644
index 000000000..91c4d25f5
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasundefined.json
@@ -0,0 +1,90 @@
+[
+ {
+ "type": "interface",
+ "name": "Cat",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "owner",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "isMemberOfBreed",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "TreatUndefinedAs",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "EmptyString"
+ }
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "breedName"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-nested.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-nested.json
new file mode 100644
index 000000000..76d138408
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-nested.json
@@ -0,0 +1,226 @@
+[
+ {
+ "type": "interface",
+ "name": "Point",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "x",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "y",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Rect",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "topleft",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "bottomright",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Widget",
+ "partial": false,
+ "members": [
+ {
+ "type": "typedef",
+ "typeExtAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ }
+ },
+ "name": "PointSequence",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Rect"
+ },
+ "name": "bounds",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "pointWithinBounds",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "p"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "allPointsWithinBounds",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "PointSequence"
+ },
+ "name": "ps"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "typedef",
+ "typeExtAttrs": [
+ {
+ "name": "Clamp",
+ "arguments": null
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "octet"
+ },
+ "name": "value",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json
new file mode 100644
index 000000000..ffdeea945
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json
@@ -0,0 +1,226 @@
+[
+ {
+ "type": "interface",
+ "name": "Point",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "x",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "y",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "typedef",
+ "typeExtAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ }
+ },
+ "name": "PointSequence",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Rect",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "topleft",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "bottomright",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Widget",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Rect"
+ },
+ "name": "bounds",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "pointWithinBounds",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "p"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "allPointsWithinBounds",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "PointSequence"
+ },
+ "name": "ps"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "typedef",
+ "typeExtAttrs": [
+ {
+ "name": "Clamp",
+ "arguments": null
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "octet"
+ },
+ "name": "value",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typesuffixes.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typesuffixes.json
new file mode 100644
index 000000000..790c444ef
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typesuffixes.json
@@ -0,0 +1,55 @@
+[
+ {
+ "type": "interface",
+ "name": "Suffixes",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "test",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": 1,
+ "nullableArray": [false],
+ "union": false,
+ "idlType": "DOMString"
+ }
+ },
+ "name": "foo"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json
new file mode 100644
index 000000000..43e25fd6b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json
@@ -0,0 +1,87 @@
+[
+ {
+ "type": "interface",
+ "name": "Union",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": true,
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": true,
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Date"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Event"
+ }
+ ]
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": true,
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Node"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ }
+ ]
+ }
+ ]
+ },
+ "name": "test",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/json/variadic-operations.json b/testing/web-platform/tests/resources/webidl2/test/syntax/json/variadic-operations.json
new file mode 100644
index 000000000..431ec0cb1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/variadic-operations.json
@@ -0,0 +1,100 @@
+[
+ {
+ "type": "interface",
+ "name": "IntegerSet",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "cardinality",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "union",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "intersection",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/syntax/opt/typedef-nested.json b/testing/web-platform/tests/resources/webidl2/test/syntax/opt/typedef-nested.json
new file mode 100644
index 000000000..f0794e74e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/opt/typedef-nested.json
@@ -0,0 +1,3 @@
+{
+ "allowNestedTypedefs": true
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js b/testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js
new file mode 100644
index 000000000..34c5a5c2b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/web/make-web-tests.js
@@ -0,0 +1,51 @@
+
+// generates tests that work in a browser
+
+// XXX
+// have it run through valid and invalid properly
+
+var pth = require("path")
+, fs = require("fs")
+, dir = function (path) {
+ return pth.join(__dirname, "..", path);
+ }
+, allFromDir = function (dir, ext, asJSON) {
+ return fs.readdirSync(dir)
+ .filter(function (it) { return ext.test(it); })
+ .map(function (it) {
+ var cnt = fs.readFileSync(pth.join(dir, it), "utf8");
+ return asJSON ? JSON.parse(cnt) : cnt;
+ });
+ }
+, data = {
+ valid: {
+ json: allFromDir(dir("syntax/json"), /\.json$/, true)
+ , idl: allFromDir(dir("syntax/idl"), /\.w?idl$/, false)
+ }
+ , invalid:{
+ json: allFromDir(dir("invalid/json"), /\.json$/, true)
+ , idl: allFromDir(dir("invalid/idl"), /\.w?idl$/, false)
+ }
+ }
+, html = [
+ "<!DOCTYPE html>"
+ , "<html>"
+ , " <head><meta charset='utf-8''><link rel='stylesheet' href='../../node_modules/mocha/mocha.css'>"
+ , " <title>WebIDL2 Browser Tests</title>"
+ , " <script>var data = " + JSON.stringify(data) + "</script>"
+ , " </head>"
+ , " <body><div id='mocha'></div>"
+ , " <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'></script>"
+ , " <script src='../../node_modules/expect.js/expect.js'></script>"
+ , " <script src='../../node_modules/mocha/mocha.js'></script>"
+ , " <script src='../../node_modules/jsondiffpatch/jsondiffpatch.min.js'></script>"
+ , " <script src='../../lib/webidl2.js'></script>"
+ , " <script>mocha.setup('bdd');</script>"
+ , " <script src='run-tests.js'></script>"
+ , " <script>mocha.run();</script>"
+ , " </body>"
+ , "</html>"
+ ].join("\n")
+;
+
+fs.writeFileSync("browser-tests.html", html, "utf8");
diff --git a/testing/web-platform/tests/resources/webidl2/test/web/run-tests.js b/testing/web-platform/tests/resources/webidl2/test/web/run-tests.js
new file mode 100644
index 000000000..a72800b8b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/web/run-tests.js
@@ -0,0 +1,48 @@
+
+describe("Parses all of the IDLs to produce the correct ASTs", function () {
+ for (var i = 0, n = data.valid.idl.length; i < n; i++) {
+ var idl = data.valid.idl[i], json = data.valid.json[i];
+ var func = (function (idl, json) {
+ return function () {
+ try {
+ // the AST contains NaN and +/-Infinity that cannot be serialised to JSON
+ // the stored JSON ASTs use the same replacement function as is used below
+ // so we compare based on that
+ var diff = jsondiffpatch.diff(json, WebIDL2.parse(idl));
+ if (diff && debug) console.log(JSON.stringify(diff, null, 4));
+ expect(diff).to.be(undefined);
+ }
+ catch (e) {
+ console.log(e.toString());
+ throw e;
+ }
+ };
+ }(idl, json));
+ it("should produce the same AST for " + i, func);
+ }
+});
+
+describe("Parses all of the invalid IDLs to check that they blow up correctly", function () {
+ for (var i = 0, n = data.invalid.idl.length; i < n; i++) {
+ var idl = data.invalid.idl[i], error = data.invalid.json[i];
+ var func = (function (idl, err) {
+ return function () {
+ var error;
+ try {
+ var ast = WebIDL2.parse(idl);
+ console.log(JSON.stringify(ast, null, 4));
+ }
+ catch (e) {
+ error = e;
+ }
+ finally {
+ expect(error).to.be.ok();
+ expect(error.message).to.equal(err.message);
+ expect(error.line).to.equal(err.line);
+ }
+
+ };
+ }(idl, error));
+ it("should produce the right error for " + i, func);
+ }
+});
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/.gitignore b/testing/web-platform/tests/resources/webidl2/test/widlproc/.gitignore
new file mode 100644
index 000000000..bffeb270d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/.gitignore
@@ -0,0 +1,3 @@
+obj/
+test/valid/obj
+test/invalid/obj
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/LICENSE b/testing/web-platform/tests/resources/webidl2/test/widlproc/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/Makefile b/testing/web-platform/tests/resources/webidl2/test/widlproc/Makefile
new file mode 100644
index 000000000..d517466e4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/Makefile
@@ -0,0 +1,158 @@
+########################################################################
+# $Id$
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+UNAME = $(shell uname)
+INCDIRS = $(OBJDIR)
+SRCDIR = src
+DOCDIR = doc
+EXAMPLESDIR = examples
+OBJDIR = obj
+
+########################################################################
+# Linux configuration
+#
+ifneq (,$(filter Linux%, $(UNAME)))
+
+CFLAGS = -g -Wall -Werror -O0 $(patsubst %, -I%, $(INCDIRS))
+OBJSUFFIX = .o
+EXESUFFIX =
+#LIBS = -lefence
+OBJOPTION = -o
+EXEOPTION = -o
+
+else
+########################################################################
+# Darwin configuration
+#
+ifneq (,$(filter Darwin%, $(UNAME)))
+
+CFLAGS = -g -Wall -Werror -O2 $(patsubst %, -I%, $(INCDIRS))
+OBJSUFFIX = .o
+EXESUFFIX =
+OBJOPTION = -o
+# The -o in the following line has a space after it, which must not be removed.
+EXEOPTION = -o
+
+else
+########################################################################
+# Windows (cygwin but using MS compiler) configuration
+#
+# this is messy - should probably use vcvars.bat
+ifneq (,$(filter CYGWIN%, $(UNAME)))
+VISUALSTUDIODIR = $(wildcard /cygdrive/c/Program*Files/Microsoft*Visual*Studio*8)
+SDKDIR = $(wildcard /cygdrive/c/Program*Files/Microsoft*SDKs/Windows/*/Lib)
+ifeq (,$(VISUALSTUDIODIR))
+VISUALSTUDIODIR = $(wildcard /cygdrive/c/Program\ Files\ */Microsoft*Visual*Studio*10*)
+endif
+ifeq (,$(VISUALSTUDIODIR))
+VISUALSTUDIODIR = $(wildcard /cygdrive/c/Program\ Files\ */Microsoft*Visual*Studio*11*)
+endif
+# this is revelvant for vs2012 and windows 8 - sdk location has changed
+ifeq (,$(SDKDIR))
+SDKDIR = $(wildcard /cygdrive/c/Program\ Files\ */Windows*Kits)
+endif
+
+ifeq (,$(VISUALSTUDIODIR))
+$(error Could not find MS Visual Studio)
+else
+WINVISUALSTUDIODIR = $(shell cygpath -w '$(VISUALSTUDIODIR)')
+WINSDKDIR = $(shell cygpath -w '$(SDKDIR)')
+
+#$(error $(VISUALSTUDIODIR))
+
+CC = \
+ Lib='$(WINVISUALSTUDIODIR)\VC\LIB;$(WINVISUALSTUDIODIR)\VC\PlatformSDK\Lib;$(WINSDKDIR)' \
+ PATH='$(VISUALSTUDIODIR)/Common7/IDE:$(VISUALSTUDIODIR)/VC/BIN:$(VISUALSTUDIODIR)/Common7/Tools:$(VISUALSTUDIODIR)/SDK/v2.0/bin:$(VISUALSTUDIODIR)/8.0/Lib/win8/um/x86:'$$PATH \
+ Include='$(WINVISUALSTUDIODIR)\VC\INCLUDE;$(WINVISUALSTUDIODIR)\VC\PlatformSDK\Include' \
+ cl
+endif
+
+CFLAGS = /nologo /WX /W3 /wd4996 /Zi /O2 $(patsubst %, /I%, $(INCDIRS))
+OBJSUFFIX = .obj
+EXESUFFIX = .exe
+OBJOPTION = /Fo
+EXEOPTION = /Fe
+
+endif
+endif
+endif
+
+########################################################################
+# Common makefile
+#
+WIDLPROC = $(OBJDIR)/widlproc$(EXESUFFIX)
+DTD = $(OBJDIR)/widlprocxml.dtd
+
+ALL = $(WIDLPROC) $(DTD)
+all : $(ALL)
+
+SRCS = \
+ comment.c \
+ lex.c \
+ main.c \
+ misc.c \
+ node.c \
+ parse.c \
+ process.c
+
+OBJS = $(patsubst %.c, $(OBJDIR)/%$(OBJSUFFIX), $(SRCS))
+$(WIDLPROC) : $(OBJS)
+ $(CC) $(CFLAGS) $(EXEOPTION)$@ $^ $(LIBS)
+
+$(OBJDIR)/%$(OBJSUFFIX) : $(SRCDIR)/%.c
+ mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) $(OBJOPTION)$@ -c $<
+
+$(OBJDIR)/%.d : $(SRCDIR)/%.c
+ mkdir -p $(dir $@)
+ cc $(patsubst %, -I%, $(INCDIRS)) -MM -MG -MT $(patsubst %.d, %$(OBJSUFFIX), $@) $< | sed '$(patsubst %, s| \(%\)| $(OBJDIR)/\1|;, $(AUTOGENHEADERS))' >$@
+
+include $(patsubst %.c, $(OBJDIR)/%.d, $(SRCS))
+
+
+$(DTD) : $(DOCDIR)/htmltodtd.xsl $(DOCDIR)/widlproc.html
+ xsltproc -html $^ >$@
+
+clean :
+ rm -f $(ALL) $(OBJS)
+
+veryclean :
+ rm -rf $(OBJDIR)
+
+SVNFILES = $(shell test -d .svn && svn info -R . | sed -n 's/^Path: \(.*\)$$/\1/p')
+SVNBRANCH = $(shell test -d .svn && svn info . | sed -n 's|^URL:.*/\([^/]*\)$$|\1|p')
+SVNREV = $(shell test -d .svn && svn info -R . | sed -n 's/^Last Changed Rev: \([0-9][0-9]*\)$$/\1/p' | sort -g | tail -1)
+
+SVNLOG = history
+$(SVNLOG) : $(SVNFILES)
+ svn log -vrHEAD:311 >$@
+
+zip : $(OBJDIR)/widlproc-$(SVNBRANCH)$(SVNREV).zip
+$(OBJDIR)/widlproc-$(SVNBRANCH)$(SVNREV).zip : $(WIDLPROC) $(DTD) $(DOCDIR)/widlproc.html $(SRCDIR)/widlprocxmltohtml.xsl Makefile $(SVNLOG)
+ rm -f $@
+ zip -j $@ $^ -x Makefile
+ zip $@ examples/*.widl examples/*.css examples/Makefile examples/README examples/*.xsl examples/*.html
+
+srczip : widlproc-src-$(SVNBRANCH)$(SVNREV).zip
+
+widlproc-src-%.zip : $(SVNFILES) $(SVNLOG)
+ zip $@ $^
+
+examples :
+ $(MAKE) -C examples SRCDIR=../src OBJDIR=../obj EXAMPLESOBJDIR=../obj/examples
+
+test : $(OBJS)
+ $(MAKE) -C test SRCDIR=../src OBJDIR=../obj
+
+.DELETE_ON_ERROR:
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/README.md b/testing/web-platform/tests/resources/webidl2/test/widlproc/README.md
new file mode 100644
index 000000000..8ed824e7d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/README.md
@@ -0,0 +1,40 @@
+# Uses
+
+widlproc can be used to validate WebIDL in W3C specifications. It serves as the basis for the [W3C Web IDL on-line checker](http://www.w3.org/2009/07/webidl-check).
+
+widlproc's generated XML is used to generate [webinos JavaScript APIs specifications](http://dev.webinos.org/specifications/draft/).
+
+# License
+
+widlproc is licensed under the Apache 2 License.
+
+# Others
+
+See also [webidl.js](https://github.com/darobin/webidl.js), a JavaScript-based Web IDL parser used by various tools in W3C.
+
+# Credits
+
+Most of the work on widlproc was done by Tim Renouf and Paddy Byers. Aplix corporation owns the copyright of the code up to June 2011.
+
+The tool is kept up to date with the changes in the spec by Dominique Hazael-Massieux, through funding from the [webinos project](http://webinos.org/) since June 2011.
+
+# Documentation
+
+See doc/widlproc.html in the tree.
+
+# Build Instructions
+
+## Windows
+
+Install requirements
+* Cygwin - must install must install libs/libxslt
+* Visual Studio express 2012 or 2010 (see difference below)
+
+makefile uses cygwin make. References are coded in the make file to detect teh current version of visual studio
+
+# Future work
+windows build could be improved to handle multipe versions with vcvars.bat
+http://stackoverflow.com/questions/62029/vs2008-command-prompt-cygwin
+
+
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl b/testing/web-platform/tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl
new file mode 100644
index 000000000..d8b7f5973
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="us-ascii"?>
+<!--====================================================================
+$Id$
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Stylesheet to extract DTD for widlprocxml from widlproc.html
+=====================================================================-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="text" encoding="us-ascii" indent="no"/>
+
+<!-- <pre class="dtd"> element -->
+<xsl:template match="pre[@class='dtd']">
+ <xsl:value-of select="."/>
+</xsl:template>
+
+<!--Ignore other text. -->
+<xsl:template match="text()" priority="-100"/>
+
+</xsl:stylesheet>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/doc/widlproc.html b/testing/web-platform/tests/resources/webidl2/test/widlproc/doc/widlproc.html
new file mode 100644
index 000000000..4eb42c39b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/doc/widlproc.html
@@ -0,0 +1,1124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--====================================================================
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=====================================================================-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<title>widlproc</title>
+<style type="text/css">
+ body { color: black; font: 10pt verdana; }
+ a:link { text-decoration: none; }
+ a:visited { text-decoration: none; }
+ a:hover { text-decoration: underline; }
+ dt { margin-top: 0.5em; }
+ dd { margin-left: 1em; margin-bottom: 0.5em; }
+ li { margin-bottom: 0; }
+ h4 { font-size: 10pt; }
+ table { border: 1px solid; border-collapse: collapse; }
+ td { border: 1px solid; }
+ th { border: 1px solid; }
+ code { background-color: #f0f0f0; }
+ pre { background-color: #f0f0f0; }
+ .indent { margin-left: 3em; }
+ .issue { background-color: #00CCCC; }
+</style>
+</head>
+<body>
+<h1>widlproc</h1>
+
+<p>Tim Renouf, Aplix Corp</p>
+<p>$Id$
+</p>
+
+<h2>Introduction</h2>
+
+<p>
+widlproc is a processor that accepts as input
+<a href="#webidl">Web IDL</a> (the 30 September 2009 editor's draft),
+with comments in a subset of the format used by
+<a href="#doxygen">Doxygen</a>.
+The format it accepts is proposed by Aplix for authoring
+<a href="#bondi">BONDI</a> interface definitions.
+</p>
+
+<p>
+The output of widlproc is an XML representation of the
+<a href="#webidl">Web IDL</a> input,
+with added XML elements representing the
+<a href="#doxygen">Doxygen</a>-like comments.
+</p>
+
+<h2>Usage</h2>
+
+<p>
+<code>widlproc <i>filename</i></code>
+</p>
+
+<p>
+widlproc reads the file named <em>filename</em>, and
+sends its XML output format to stdout.
+</p>
+
+<h2>Input format</h2>
+
+<p>
+The input format accepted by widlproc is
+<a href="#webidl">Web IDL</a>
+(with an extension used in the
+<a href="#w3cgeo">W3C Geolocation API</a>),
+with comments in a format reminiscent of that used by
+<a href="#doxygen">Doxygen</a>.
+</p>
+
+<h3>Web IDL extension from W3C geolocation API</h3>
+
+<h4>double</h4>
+
+<p>
+<code>double</code> is allowed as a DeclarationType or a BoxedType.
+</p>
+
+<h3>Doxygen-like comment introduction</h3>
+
+<p>
+Only a small subset of Doxygen functionality is supported by
+widlproc, plus additions to handle the BONDI concepts of API features
+and device capabilities.
+</p>
+
+<p>
+In particular, no links are added automatically. (This could be added
+in the future.)
+</p>
+
+<h3>Doxygen comment block</h3>
+
+<h4>Comment referral point</h4>
+
+<p>
+Each <em>Doxygen comment block</em> refers to a <em>comment referral
+point</em> in the Web IDL, one of
+module, interface, exception, const, attribute, operation or argument.
+</p>
+
+<h4>Block comment</h4>
+
+<p>
+A block comment (delimited by <code>/* */</code>) whose first character
+after the <code>/*</code> is <code>!</code> or a second <code>*</code>
+is a <em>Doxygen comment block</em>.
+</p>
+
+<p>
+Normally the comment block refers to the next comment referral point in
+the Web IDL.
+If the first character is <code>&lt;</code>, so the comment block is introduced
+with <code>/**&lt;</code> or <code>/*!&lt;</code> , then the comment block
+refers back to the previous comment referral point.
+</p>
+
+<p>
+The text of the comment block
+excludes the initial <code>!</code> or <code>*</code> (and the <code>&lt;</code>
+for a referring back block),
+and excludes an initial (after whitespace) <code>*</code>
+on each line,
+and, when not in a <a href="#code"><code>\code</code></a> block,
+excludes any line consisting entirely of whitespace, then <code>*</code>
+characters, then whitespace.
+</p>
+
+<p>
+widlproc does not support Doxygen commands to force a comment
+block to refer to a different referral point.
+</p>
+
+<h4>Inline comments</h4>
+
+<p>
+The maximal sequence of inline comments (delimited by <code>//</code>)
+on adjacent lines, where all of the following conditions hold:
+</p>
+<ul>
+<li>
+each has a first character after the <code>/</code> of <code>!</code> or
+a third <code>/</code>;
+<li>
+no comment referral point intervenes;
+<li>
+either each comment in the sequence starts with a <code>&lt;</code>
+(see below), or none does;
+<li>
+the sequence contains at least two inline comments, or, if only one,
+then it starts with <code>&lt;</code> (see below);
+</ul>
+<p>
+forms a <em>Doxygen comment block</em>.
+</p>
+
+<p>
+Normally the comment block refers to the next comment referral point in
+the Web IDL.
+If the first character of each comment is <code>&lt;</code>, so each
+comment in the block is introduced
+with <code>///&lt;</code> or <code>//!&lt;</code> , then the comment block
+refers back to the previous comment referral point.
+</p>
+
+<p>
+The text of the comment block
+excludes the initial <code>!</code> or <code>/</code> (and the <code>&lt;</code>
+for a referring back block) of each inline comment,
+and, when not in a <a href="#code"><code>\code</code></a> block,
+excludes any line consisting entirely of whitespace, then <code>/</code>
+characters, then whitespace.
+</p>
+
+<p>
+widlproc does not support Doxygen commands to force a comment
+block to refer to a different referral point.
+</p>
+
+<h3>Paragraph</h3>
+
+<p>
+A comment block is broken into zero or more <em>paragraph</em>s.
+One or more blank lines break the paragraphs (unless in a
+<a href="#code"><code>\code</code></a> block).
+</p>
+
+<p>
+Certain commands (below) also start a new paragraph.
+</p>
+
+<p>
+An
+<a href="#html">HTML block element</a>
+is a paragraph.
+A blank line (other than in a
+<a href="#code"><code>\code</code></a> block)
+implicitly closes any open HTML elements, thus ending the paragraph.
+</p>
+
+<h3>Doxygen-like commands</h3>
+
+<p>
+widlproc supports a small subset of Doxygen commands, plus some additions
+to handle BONDI API features and device capabilities.
+</p>
+
+<p>
+A command is always introduced with a <code>\</code> character.
+The Doxygen alternative (from JavaDoc) of <code>@</code> is not
+supported.
+</p>
+
+<h4 id="api-feature">\api-feature</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of an API feature
+used by the method being documented. The remainder of the paragraph is
+any description required of how (eg in what circumstance) the API feature
+is used.
+</p>
+
+<h4>\name</h4>
+
+<p>
+Declares a name for the document node associated with the current referral
+point. This is useful for the root document node that otherwise does not have
+a WebIDL identifier.
+</p>
+
+<h4>\author</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph contains
+information about a single author of the specification. Multiple
+<code>\author</code> commands should be used for multiple authors.
+</p>
+
+<p>
+(Here widlproc differs from Doxygen; Doxygen also allows
+multiple authors on separate lines to appear in one <code>\author</code>
+paragraph.)
+</p>
+
+<h4>\b</h4>
+
+<p>
+This renders the next word as bold. It is equivalent to enclosing the
+next word with <code>&lt;b> &lt;/b></code>.
+</p>
+
+<h4>\brief</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph contains a brief
+description of the entity being documented.
+</p>
+
+<h4 id="code">\code, \endcode</h4>
+
+<p>
+<code>\code</code>
+starts a new paragraph which is a <em>code block</em>. The code block
+ends at the next <code>\endcode</code> command.
+</p>
+
+<p>
+Within the code block, whitespace and newlines are passed verbatim into
+the output.
+</p>
+
+<h4 id="def-api-feature">\def-api-feature</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of the API feature
+which is defined here. The description is an <em>def-api-feature block</em>,
+consisting of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#device-cap"><code>\device-cap</code></a>
+paragraph.
+</p>
+
+<h4 id="def-api-feature-set">\def-api-feature-set</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of the API feature
+set which is defined here. The description is an <em>def-api-feature-set block</em>,
+consisting of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#device-cap"><code>\api-feature</code></a>
+paragraph.
+</p>
+
+<h4>\def-device-cap</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of the device capability
+which is defined here. The description consists of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#param"><code>\param</code></a>
+paragraph.
+</p>
+
+<h4 id="def-instantiated">\def-instantiated</h4>
+
+<p>
+Starts a new paragraph. The description is an <em>def-instantiated block</em>,
+consisting of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#api-feature"><code>\api-feature</code></a>
+paragraph.
+</p>
+
+<h4 id="device-cap">\device-cap</h4>
+
+<p>
+Starts a new paragraph.
+This command can appear only inside an
+<a href="#def-api-feature">def-api-feature block</a>.
+The following word is the name of a device capability
+used by the API feature being documented.
+The remainder of the paragraph is
+any description required of how (eg in what circumstance) the device capability
+is used.
+</p>
+
+<h4>\n</h4>
+
+<p>
+Creates a line break in the output.
+</p>
+
+<h4 id="param">\param</h4>
+
+<p>
+Starts a new paragraph. This takes the following word as the name of
+a parameter (argument) of the entity being documented, then makes the
+remainder of the paragraph refer to that parameter.
+</p>
+
+<h4>\return</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph is made to refer to
+the return type of the entity being documented.
+</p>
+
+<h4>\throw</h4>
+
+<p>
+Starts a new paragraph. The next word is taken to be the name of an
+exception thrown by the entity being documented, and the remainder of
+the paragraph documents that exception (in the <code>raises</code> list of
+an <code>operation</code>, or the <code>setraises</code>
+clause of an <code>attribute</code>).
+</p>
+
+<h4>\version</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph contains
+version number information.
+</p>
+
+<h3>Escape sequences</h3>
+
+<p>
+The following escape sequences are recognized in a comment block:
+</p>
+
+<table>
+<tr>
+<th>escape sequence
+<th>result
+<tr>
+<td><code>\\</code>
+<td><code>\</code>
+<tr>
+<td><code>\&amp;</code>
+<td><code>&amp;</code> (escaped to <code>&amp;amp;</code> in output XML)
+<tr>
+<td><code>\$</code>
+<td><code>$</code>
+<tr>
+<td><code>\#</code>
+<td><code>#</code>
+<tr>
+<td><code>\&lt;</code>
+<td><code>&lt;</code> (escaped to <code>&amp;lt;</code> in output XML)
+<tr>
+<td><code>\></code>
+<td><code>></code>
+<tr>
+<td><code>\%</code>
+<td><code>%</code>
+</table>
+
+<p>
+Some of these escape sequences are used to avoid Doxygen features that
+widlproc does not currently implement. In particular,
+widlproc insists on a <code>$</code> being escaped, to
+allow for possible future functionality.
+</p>
+
+<h3 id="html">HTML in comments</h3>
+
+<p>
+widlproc accepts a small subset of HTML elements.
+</p>
+
+<p>
+An HTML block element is a paragraph.
+A blank line (other than in a
+<a href="#code"><code>\code</code></a> block)
+implicitly closes any open HTML elements, thus ending the paragraph.
+</p>
+
+<p>
+The following HTML block elements are accepted:
+<code>dl</code>
+<code>ol</code>
+<code>p</code>
+<code>table</code>
+<code>ul</code>
+</p>
+
+<p>
+The following HTML inline elements are accepted:
+<code>a</code>
+<code>img</code>
+<code>b</code>
+<code>br</code>
+<code>em</code>
+</p>
+
+<p>
+The following HTML elements are accepted where valid inside one of the
+other elements:
+<code>dd</code>
+<code>dt</code>
+<code>li</code>
+<code>td</code>
+<code>th</code>
+<code>tr</code>
+</p>
+
+
+<h2>Output format</h2>
+
+<p>
+The output of widlproc is an XML representation of the
+<a href="#webidl">Web IDL</a>,
+with added XML elements representing the
+<a href="#doxygen">Doxygen</a>-like comments.
+</p>
+
+<h3>Annotated document type declaration</h3>
+
+<pre class="dtd">
+&lt;!-- Autogenerated from widlproc.html : do not edit. -->
+</pre>
+
+<h4>Entities used elsewhere</h4>
+
+<pre class="dtd">
+&lt;!ENTITY % block 'dl | p | table | ul' >
+&lt;!ENTITY % Block '(%block;)*' >
+&lt;!ENTITY % inline 'a | b | br | em | img' >
+&lt;!ENTITY % Inline '(#PCDATA | %inline;)*' >
+&lt;!ENTITY % Flow '(#PCDATA | %inline; | %block;)*' >
+
+&lt;!ELEMENT webidl (#PCDATA | ref)* >
+</pre>
+
+<p>
+The <code>&lt;webidl></code> element contains the literal text of the
+original Web IDL that the parent
+element was parsed from, minus the comments, with each reference to
+an interface name
+enclosed in a <code>&lt;ref></code>..<code>&lt;/ref></code>.
+</p>
+
+<h4>Definitions</h4>
+
+<p>
+<em>Definitions</em> is the root element of the XML document.
+</p>
+
+<p>
+The <em>ExtendedAttributeList</em> specifies any extended attributes
+for the <em>Interface</em>, <em>Dictionary</em>, <em>Exception</em>,
+<em>Typedef</em>, <em>Valuetype</em> or <em>Const</em> in the
+<em>Definition</em>.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Definitions ( webidl, descriptive?, (Interface | Dictionary | Callback
+ | Enum | Exception | Typedef | Implements)*) >
+</pre>
+
+<h4>Interface</h4>
+
+<p>
+An <em>Interface</em> represents an interface. The <em>name</em>
+attribute specifies the name of the interface. The <em>descriptive</em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the interface.
+</p>
+
+<p>The <em>partial</em> attribute indicates that the definition of the interface complements an existing definition. The <em>callback</em> attribute specificies that a given interface is a callback interface.</p>
+
+<p>
+The <em>InterfaceInheritance</em> element indicates that the interface
+inherits from other interface(s). Each <em>Name</em> in the
+<em>InterfaceInheritance</em> has a <em>name</em> attribute giving the
+scoped name of the interface being inherited from.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Interface (webidl, descriptive?, ExtendedAttributeList?,
+ InterfaceInheritance?, (Const | Attribute | Operation | Stringifier* | Serializer* | Iterator | IteratorObject)* ) >
+&lt;!ATTLIST Interface name CDATA #REQUIRED
+ partial (partial) #IMPLIED
+ callback (callback) #IMPLIED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT InterfaceInheritance (Name+) >
+
+&lt;!ELEMENT Name EMPTY >
+&lt;!ATTLIST Name name CDATA #REQUIRED >
+</pre>
+
+<h4>Dictionary</h4>
+
+<p>
+A <em>Dictionary</em> represents a dictionary. The <em>name</em>
+attribute specifies the name of the dictionary. The <em>descriptive</em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the dictionary.
+</p>
+
+<p>The <em>partial</em> attribute indicates that the definition of the interface complements an existing definition.</p>
+
+<p>
+The <em>DictionaryInheritance</em> element indicates that the dictionary
+inherits from other dictionary(s). Each <em>Name</em> in the
+<em>DictionaryInheritance</em> has a <em>name</em> attribute giving the
+scoped name of the dictionary being inherited from.
+</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Dictionary (webidl, descriptive?, DictionaryInheritance?, DictionaryMember* ) >
+&lt;!ATTLIST Dictionary name CDATA #REQUIRED
+ partial (partial) #IMPLIED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT DictionaryInheritance (Name+) >
+</pre>
+
+<h4>Callback</h4>
+
+<p>
+A <em>Callback</em> represents a callback type. The <em>name</em>
+attribute specifies the name of the dictionary. The <em>descriptive</em> element
+provides its documentation if any.</p>
+
+<p>The <em>Type</em> element specifies its return type.</p>
+
+<p>
+An <em>Argument</em> is an argument to an operation.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name if it has one.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Callback (webidl, descriptive?, Type, ArgumentList? ) >
+&lt;!ATTLIST Callback name CDATA #REQUIRED
+ id CDATA #REQUIRED>
+</pre>
+
+
+<h4>Enum</h4>
+
+<p>
+An <em>Enum</em> represents an enumeration. The <em>name</em>
+attribute specifies the name of the enumeration. The <em>descriptive</em> element
+provides its documentation if any.
+</p>
+
+<p>
+The <em>EnumValue</em> element indicates the values defined for that enumeration in its <em>stringvalue</em> attribute.
+</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Enum (webidl, descriptive?, EnumValue* ) >
+&lt;!ATTLIST Enum name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT EnumValue (webidl, descriptive?) >
+&lt;!ATTLIST EnumValue stringvalue CDATA #REQUIRED >
+</pre>
+
+
+
+<h4>Exception</h4>
+
+<p>
+An <em>Exception</em> represents an exception.
+The <em>name</em>
+attribute specifies the name of the exception.
+The <em>descriptive</em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the exception.
+</p>
+
+<p>
+An <em>ExceptionField</em> represents a field in an exception.
+The <em>name</em>
+attribute specifies the name of the field.
+The <em>Type</em> element specifies its type.
+The <em>descriptive></em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the field.
+</p>
+
+<p>
+The <em>ExceptionInheritance</em> element indicates that the exception
+inherits from another exception. The <em>Name</em> in the
+<em>ExceptionInheritance</em> has a <em>name</em> attribute giving the
+scoped name of the exception being inherited from.
+</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Exception (webidl, descriptive?, ExtendedAttributeList?, ExceptionInheritance?,
+ (Const | ExceptionField)* ) >
+&lt;!ATTLIST Exception name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT ExceptionInheritance (Name) >
+&lt;!ELEMENT ExceptionField (webidl, descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST ExceptionField name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+</pre>
+
+<h4>Typedef</h4>
+
+<p>
+A <em>Typedef</em> represents a type definition.
+The <em>name</em>
+attribute specifies the name of the new type.
+The <em>Type</em> element specifies it in terms of other types.
+The <em>descriptive></em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the typedef.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Typedef (webidl, descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST Typedef name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+</pre>
+
+<h4>Implements</h4>
+
+<p>
+An <em>Implements</em> represents Web IDL's
+<code><i>ScopedName</i> implements <i>ScopedName</i>;</code>
+syntax. The <em>name1</em> and <em>name2</em> attributes give the
+first and second scoped names respectively.
+The <em>descriptive></em> element
+provides the <em>Implements</em>'s documentation if any.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Implements (webidl, descriptive?, ExtendedAttributeList?) >
+&lt;!ATTLIST Implements name1 CDATA #REQUIRED
+ name2 CDATA #REQUIRED >
+</pre>
+
+<h4>Const</h4>
+
+<p>
+<em>Const</em> represents Web IDL's
+<code>const <i>Type</i> <i>identifier</i> = <i>ConstExpr</i>;</code>
+syntax.
+The <em>Type</em> specifies the constant's type, the
+<em>name</em> attribute specifies the constant's name, and the
+<em>value</em> attribute specifies its value.
+The <em>descriptive></em> element
+provides the <em>Const</em>'s documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the const.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Const (webidl, descriptive?, ExtendedAttributeList?, Type) >
+&lt;!ATTLIST Const name CDATA #REQUIRED
+ value CDATA #IMPLIED
+ id CDATA #REQUIRED >
+</pre>
+
+<h4>Stringifier</h4>
+
+<p>
+A <em>Stringifier</em> represents the Web IDL <code>stringifier;</code>
+syntax as an interface member.
+The <em>descriptive></em> element
+provides the <em>Stringifier</em>'s documentation if any.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Stringifier (webidl, descriptive?, ExtendedAttributeList?) >
+</pre>
+
+<h4>Attribute</h4>
+
+<p>
+An <em>Attribute</em> represents an attribute as an interface member.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name. Each of the <em>stringifier</em>, <em>static</em> and
+<em>readonly</em> attributes is set to a value the same as the attribute
+name when the corresponding keyword appears in the Web IDL input. The <em>inherit</em> attribute is set to <em>inherit</em> when the attribute inherits its getter.
+</p>
+
+
+<p>
+The <em>descriptive></em> element provides the attribute's documentation
+if any.
+The <em>id</em> attribute specifies the absolute scoped name of the attribute.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Attribute (webidl, descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST Attribute stringifier (stringifier) #IMPLIED
+ readonly (readonly) #IMPLIED
+ inherit (inherit) #IMPLIED
+ static (static) #IMPLIED
+ name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+
+</pre>
+
+
+<h4>Operation</h4>
+
+<p>
+An <em>Operation</em> represents a method on interface.
+The <em>Type</em> element specifies its return type. The <em>name</em>
+attribute specifies its name.
+</p>
+
+<p>
+Each of the <em>stringifier</em>, <em>static</em>, <em>getter</em>,
+<em>setter</em>, <em>creator</em>, <em>deleter</em> and <em>legacycaller</em>, <em>serializer</em>
+attributes is set to a value the same as the attribute
+name when the corresponding keyword appears in the Web IDL input.
+</p>
+
+
+<p>
+The <em>descriptive></em> element provides the attribute's documentation
+if any.
+The <em>id</em> attribute specifies the absolute scoped name of the operation if it has one.
+</p>
+
+<p>
+An <em>Argument</em> is an argument to an operation.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name if it has one.
+</p>
+
+<p>
+Each of the <em>optional</em> and <em>ellipsis</em>
+attributes is set to a value the same as the attribute
+name when the corresponding syntax appears in the Web IDL input.
+</p>
+
+<p>The
+<em>value</em> attribute used on optional arguments specifies default value for non-string values, and <em>stringvalue</em> for string values.</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Operation (webidl, descriptive?, ExtendedAttributeList?,
+ (Type), ArgumentList) >
+&lt;!ATTLIST Operation stringifier (stringifier) #IMPLIED
+ static (static) #IMPLIED
+ getter (getter) #IMPLIED
+ setter (setter) #IMPLIED
+ creator (creator) #IMPLIED
+ deleter (deleter) #IMPLIED
+ serializer (serializer) #IMPLIED
+ legacycaller (legacycaller) #IMPLIED
+ name NMTOKEN #IMPLIED
+ id NMTOKEN #IMPLIED >
+
+
+&lt;!ELEMENT ArgumentList (Argument*) >
+
+&lt;!ELEMENT Argument (descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST Argument
+ optional (optional) #IMPLIED
+ ellipsis (ellipsis) #IMPLIED
+ value CDATA #IMPLIED
+ stringvalue CDATA #IMPLIED
+ name NMTOKEN #REQUIRED >
+</pre>
+
+<h4>Serializer</h4>
+<p>A <em>Serializer</em> represents a serializer for an interface, either defined in the prose or via a pattern.</p>
+
+<p>The <em>descriptive</em> element provides the serializer's documentation if any.</p>
+
+
+<p>The <em>attribute</em> attribute defines the attribute that is used for serialization if any.</p>
+
+<p>The optional <em>Map</em> and <em>List</em> elements describe the pattern (if any) for the serializer. They take <em>PatternAttribute</em> elements with a <em>name</em> attribute that describes the attributes used for serialization.</p>
+
+<p><em>Map</em> elements take a <em>pattern</em> attribute that can be set to either "getter" (if the getter is used for serialization), "all" if all serializable attributes are to be used, or "selection" if the attributes named as children elements are to be used. Optionally, they take a <em>inherit</em> attribute set to "inherit" if the serialization takes also into account inherited attributes.</p>
+
+<p><em>List</em> elements take a <em>pattern</em> attribute that can be set to either "getter" (if the getter is used for serialization), or "selection" if the attributes named as children elements are to be used.</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Serializer (webidl, descriptive?, ExtendedAttributeList?, (Map | List)?) >
+&lt;!ATTLIST Serializer attribute CDATA #IMPLIED >
+
+&lt;!ELEMENT Map ((PatternAttribute*)) >
+
+&lt;!ATTLIST Map inherit (inherit) #IMPLIED
+ pattern (getter|all|selection) #REQUIRED>
+
+&lt;!ELEMENT List ((PatternAttribute*)) >
+
+&lt;!ATTLIST List pattern (getter|selection) #REQUIRED>
+
+&lt;!ELEMENT PatternAttribute EMPTY>
+&lt;!ATTLIST PatternAttribute name CDATA #REQUIRED>
+
+</pre>
+
+<h4>Iterator</h4>
+<p>An <em>Iterator</em> element defines whether the interface has a custom iterator; the type of the iterated objects is defined in the <em>Type</em> child. If that interator implements a particular interface, the name of that interface is set in the <em>interface</em> attribute.</p>
+<pre class="dtd">
+&lt;!ELEMENT Iterator (webidl, descriptive?, ExtendedAttributeList?, Type) >
+&lt;!ATTLIST Iterator interface CDATA #IMPLIED>
+</pre>
+
+<h4>IteratorObject</h4>
+<p>An <em>IteratorObject</em> element denotes that the interface serves as an iterator object interface; the type of the iterated objects is defined in the <em>Type</em> child.</p>
+
+<pre class="dtd">
+&lt;!ELEMENT IteratorObject (webidl, descriptive?, ExtendedAttributeList?, Type) >
+</pre>
+
+
+<h4>DictionaryMember</h4>
+
+<p>
+A <em>DictionaryMember</em> represents a member of a dictionary.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name.
+</p>
+
+<p>
+The <em>descriptive></em> element provides the dictionary member's documentation
+if any.
+The <em>id</em> attribute specifies the absolute scoped name of the attribute.
+</p>
+
+<p>The
+<em>value</em> attribute specifies its value for non-string values, and <em>stringvalue</em> for string values.</p>
+
+<pre class="dtd">
+&lt;!ELEMENT DictionaryMember (webidl, descriptive?, ExtendedAttributeList?, Type) >
+&lt;!ATTLIST DictionaryMember name CDATA #REQUIRED
+ id CDATA #REQUIRED
+ value CDATA #IMPLIED
+ stringvalue CDATA #IMPLIED >
+
+</pre>
+
+
+<h4>Extended attributes</h4>
+
+<p>
+An <em>ExtendedAttributeList</em> contains one or more
+<em>ExtendedAttribute</em> element. Each <em>ExtendedAttribute</em>
+has:
+</p>
+<ul>
+<li>
+a <em>name</em> attribute giving the name of the extended attribute;
+<li>
+if the extended attribute contains an <code>=</code> sign followed by a
+value, a <em>value</em> attribute giving the value, which is a scoped
+name or an identifier;
+<li>
+if the extended attribute contains parentheses (either with or without
+an <code>=</code> sign), an <em>ArgumentList</em> element giving the
+contents of the parentheses.
+</ul>
+<p>
+If the <em>value</em> attribute and the <em>ArgumentList</em> element are
+both present, then <em>value</em> must give an identifier rather than
+a scoped name.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT ExtendedAttributeList (ExtendedAttribute+) >
+
+&lt;!ELEMENT ExtendedAttribute (webidl, ArgumentList?) >
+&lt;!ATTLIST ExtendedAttribute name NMTOKEN #REQUIRED
+ value CDATA #IMPLIED >
+</pre>
+
+<h4>Type</h4>
+
+<p>
+<em>Type</em> represents a type. It has one of these forms:
+</p>
+<ul>
+<li>
+The <code>any</code>, <code>object</code> and <code>void</code>
+types have the attribute
+<em>type</em> set to the type, and no other attributes or elements.
+Note that the <code>void</code> type appears only when the <em>Type</em>
+element is a child of <em>Operation</em>.
+<li>
+A type that is an interface has the attribute <em>name</em> set to the
+name of that interface, and no other attributes or elements.
+<li>
+For the primitive types <code>short</code>, <code>unsigned short</code>,
+<code>long</code>, <code>unsigned long</code>, <code>long long</code>,
+<code>unsigned long long</code>, <code>float</code>, <code>double</code>,
+<code>boolean</code>, <code>octet</code>, <code>byte</code> and <code>DOMString</code>,
+there is an attribute <em>type</em>
+whose value is one of those strings, and no other attributes or elements.
+However, if the type was specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+</ul>
+<p>
+The restrictions on which combinations of elements and attributes are
+permitted are not encoded by the DTD.
+</p>
+<p>
+The <em>descriptive</em> element provides the documentation
+if any, when the <em>Type</em> is a child of <em>Operation</em>, and thus
+representing an operation's return type.
+</p>
+
+<p>The <em>ExtendedAttributeList</em> element provides the optional extended attributes that can be defined for a type through typedef, &agrave; la <code>typedef [Clamp] octet Value;</code>.</p>
+
+<!-- can't use enumerated values for the values of type, since DTD don't allow enumerated values to have space in them (which would be needed e.g. for "long long") -->
+<pre class="dtd">
+&lt;!ELEMENT Type (descriptive?, ExtendedAttributeList?, Type*) >
+&lt;!ATTLIST Type type CDATA #IMPLIED
+ name NMTOKEN #IMPLIED
+ nullable (nullable) #IMPLIED >
+</pre>
+
+<h4>Sequence</h4>
+
+<p>For a sequence type, the <em>Type</em> element with an attribute <em>type</em> set to <em>sequence</em> contains an element <em>Type</em> giving the sequence element type, and no other attributes or elements. If the sequence is specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+
+
+<h4>Array</h4>
+
+<p>For an array type, the <em>Type</em> element with an attribute <em>type</em> set to <em>array</em> contains an element <em>Type</em> giving the array element type. If the array is specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+
+<h4>Union</h4>
+
+<p>For a union type, the <em>Type</em> element with an attribute <em>type</em> set to <em>union</em> contains at least two element <em>Type</em> giving the union members type. If the union is specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+
+
+
+<h4>Descriptive elements</h4>
+
+<p>
+The following elements contain documentation, extracted from the
+Doxygen-like comments in the input. <code>&lt;param></code>
+derives only from a <code>\param</code> command used inside a
+<code>\def-device-cap</code> block; any other <code>\param</code> command
+is linked to a parameter (argument) of the method being documented.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT descriptive (description | brief | throw | author
+ | version | Code | api-feature | device-cap | def-api-feature
+ | def-api-feature-set | def-device-cap | def-instantiated | param)* >
+
+&lt;!ELEMENT description %Block; >
+
+&lt;!ELEMENT brief %Inline; >
+
+&lt;!ELEMENT throw %Inline; >
+
+&lt;!ELEMENT author %Inline; >
+
+&lt;!ELEMENT version %Inline; >
+
+&lt;!ELEMENT Code %Inline; >
+
+&lt;!ELEMENT api-feature %Inline; >
+&lt;!ATTLIST api-feature identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT device-cap %Inline; >
+&lt;!ATTLIST device-cap identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT param %Inline; >
+&lt;!ATTLIST param identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT def-api-feature (descriptive?) >
+&lt;!ATTLIST def-api-feature identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT def-api-feature-set (descriptive?) >
+&lt;!ATTLIST def-api-feature-set identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT def-instantiated (descriptive?) >
+
+&lt;!ELEMENT def-device-cap (descriptive?) >
+&lt;!ATTLIST def-device-cap identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT ref (#PCDATA) >
+</pre>
+
+<h4>XHTML elements</h4>
+
+<p>
+The following XHTML elements are part of widlprocxml:
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT a %Inline; >
+&lt;!ATTLIST a href CDATA #REQUIRED >
+
+&lt;!ELEMENT b %Inline; >
+
+&lt;!ELEMENT br EMPTY >
+
+&lt;!ELEMENT dd %Flow; >
+
+&lt;!ELEMENT dl ((dt | dd)*) >
+
+&lt;!ELEMENT dt %Inline; >
+
+&lt;!ELEMENT em %Inline; >
+
+&lt;!ELEMENT img %Inline; >
+&lt;!ATTLIST img src CDATA #REQUIRED
+ alt CDATA #IMPLIED>
+
+
+&lt;!ELEMENT li %Flow; >
+
+&lt;!ELEMENT p %Inline; >
+
+&lt;!ELEMENT table (tr*) >
+
+&lt;!ELEMENT td %Flow; >
+
+&lt;!ELEMENT th %Flow; >
+
+&lt;!ELEMENT tr ((th | td)*) >
+
+&lt;!ELEMENT ul (li*) >
+</pre>
+
+
+<h2>Bibliography</h2>
+
+<p id="bondi">
+BONDI - an open source industry collaboration for widget and web technologies,
+<a href="http://bondi.omtp.org/">http://bondi.omtp.org/</a>
+</p>
+
+<p id="doxygen">
+Doxygen Source code documentation generator tool,
+<a href="http://www.stack.nl/~dimitri/doxygen/index.html">
+http://www.stack.nl/~dimitri/doxygen/index.html</a>
+</p>
+
+<p id="w3cgeo">
+W3C Geolocation API Specification Editor's Draft 3 April 2009,
+<a href="http://dev.w3.org/geo/api/spec-source.html">
+http://dev.w3.org/geo/api/spec-source.html</a>
+</p>
+
+<p id="webidl">
+Web IDL W3C Editor's Draft 3 May 2011,
+<a href="http://dev.w3.org/2006/webapi/WebIDL">http://dev.w3.org/2006/webapi/WebIDL</a>
+</p>
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/Makefile b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/Makefile
new file mode 100644
index 000000000..614453d23
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/Makefile
@@ -0,0 +1,79 @@
+########################################################################
+# $Id$
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+UNAME = $(shell uname)
+EXAMPLESDIR = .
+# The settings of SRCDIR (where to find the xsl style sheets), OBJDIR (where to
+# find widlproc and widlprocxml.dtd) and EXAMPLESOBJDIR (where to put the
+# resulting html files and any intermediate files) reflect the directory
+# structure of the released widlproc.zip file when unzipped. ../Makefile calls
+# this Makefile with these settings overridden to reflect the directory
+# structure in svn.
+SRCDIR = ..
+OBJDIR = ..
+EXAMPLESOBJDIR = obj
+
+########################################################################
+# Linux configuration
+#
+ifneq (,$(filter Linux%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Darwin configuration
+#
+ifneq (,$(filter Darwin%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Windows (cygwin but using MS compiler) configuration
+#
+ifneq (,$(filter CYGWIN%, $(UNAME)))
+
+EXESUFFIX = .exe
+
+endif
+endif
+endif
+
+########################################################################
+# Common makefile
+#
+WIDLPROC = $(OBJDIR)/widlproc$(EXESUFFIX)
+DTD = $(OBJDIR)/widlprocxml.dtd
+
+WIDLS = $(patsubst $(EXAMPLESDIR)/%, %, $(wildcard $(EXAMPLESDIR)/*.widl))
+
+test : $(patsubst %.widl, $(EXAMPLESOBJDIR)/%.html, $(WIDLS)) $(EXAMPLESOBJDIR)/widlhtml.css
+ @echo "$@ pass"
+
+$(EXAMPLESOBJDIR)/%.html : $(EXAMPLESOBJDIR)/%.widlprocxml $(SRCDIR)/widlprocxmltohtml.xsl Makefile
+ cp $(SRCDIR)/widlprocxmltohtml.xsl $(dir $@)/
+ xsltproc $(dir $@)/widlprocxmltohtml.xsl $< >$@
+
+$(EXAMPLESOBJDIR)/%.widlprocxml : $(EXAMPLESDIR)/%.widl $(WIDLPROC) $(DTD) Makefile
+ mkdir -p $(dir $@)
+ $(WIDLPROC) $< >$@
+ cp $(OBJDIR)/widlprocxml.dtd $(dir $@)/
+ xmllint --noout --dtdvalid $(DTD) $@
+
+$(EXAMPLESOBJDIR)/widlhtml.css : $(EXAMPLESDIR)/widlhtml.css
+ cp $< $@
+
+.DELETE_ON_ERROR:
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/README b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/README
new file mode 100644
index 000000000..efbb72dda
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/README
@@ -0,0 +1,41 @@
+########################################################################
+# $Id$
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+This examples directory contains two of the BONDI .widl files, a Makefile
+that processes them to generate html, and a .css file that the resulting
+html uses.
+
+The Makefile processes the .widl files as follows:
+
+ 1. For each .widl, generate the .widlprocxml file (an XML representation
+ of the information in the .widl) using widlproc.
+
+ 2. Validate (using xmllint) each .widlprocxml against the DTD.
+
+ 3. We want any reference in the resulting html to a type elsewhere in the
+ API to be a link. This is where we achieve this. First generate a
+ list of fqids (fully qualified identifiers) from fqid attributes in
+ the XML by running all .widlprocxml files through the style sheet
+ widlprocxmlfqids.xsl.
+
+ 4. Turn that list of fqids into a sed script that turns a <ref> to an
+ fqid into a <ref ref=".."> to the fqid in the right .html file.
+
+ 5. For each .widlprocxml file, generate a .widlprocxml2 file by running
+ it through the sed script generated above.
+
+ 6. For each .widlprocxml2 file, generate a .html file by running it through
+ the widlprocxmltohtml.xsl style sheet.
+
+See the Makefile for details.
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/bondi.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/bondi.widl
new file mode 100644
index 000000000..200b95fe9
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/bondi.widl
@@ -0,0 +1,227 @@
+/*
+ * Licensed to OMTP Ltd. (OMTP) under one or more contributor license agreements.
+ * See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership.
+ *
+ * The Reference Implementation (save for such parts of the reference implementation made
+ * available under separate terms and conditions) is made available under the terms of the
+ * Apache License, version 2.0, subject to the condition that any "Works" and "Derivative
+ * Works" used or distributed for commercial purposes must be and remain compliant with the
+ * BONDI specification as promulgated by OMTP in each release. Your implementation of the
+ * Reference Implementation (whether object or source) must maintain these conditions, and
+ * you must notify any recipient of this condition in a conspicuous way.
+ *
+ * You may not use this BONDI Reference Implementation except in compliance with the License.
+ *
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 or at
+ * http://bondi.omtp.org/BONDI-LICENSE-2.0
+ */
+
+/**
+ * \brief Common BONDI functionality.
+ *
+ * These definitions can be used in all other BONDI modules as dependencies.
+ * \version 1.1
+ */
+module bondi {
+
+ /**
+ * \brief Array of DOMStrings.
+ */
+ typedef sequence<DOMString> StringArray;
+
+ /**
+ * \brief Array of 8-bit unsigned integer values.
+ */
+ typedef sequence<octet> ByteArray;
+
+ /**
+ * \brief Array of 16-bit signed integer values.
+ */
+ typedef sequence<short> ShortArray;
+
+ /**
+ * \brief Array of 32-bit signed integer values.
+ */
+ typedef sequence<long> LongArray;
+
+ /**
+ * \brief Array of floating point values.
+ */
+ typedef sequence<float> FloatArray;
+
+ /**
+ * \brief Generic Map object.
+ */
+ typedef Object Map;
+
+ /**
+ * \brief Generic success callback interface.
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface SuccessCallback {
+ /**
+ * \brief Method invoked when the asynchronous call completes successfully
+ */
+ void onSuccess();
+ };
+
+
+ /**
+ * \brief Success callback interface for requestFeature invocations
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface RequestFeatureSuccessCallback {
+ /**
+ * \brief Method invoked upon a succesful requestFeature invocation
+ *
+ * \param ob Object implementing the JavaScript API associated with the requested Feature.
+ */
+ void onSuccess(in Object ob);
+ };
+
+
+ /**
+ * \brief Generic error callback interface.
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface ErrorCallback {
+ /**
+ * \brief Method invoked when an error occurs
+ *
+ * \param error The error that is raised.
+ */
+ void onError(in GenericError error);
+ };
+
+ /**
+ * \brief Generic error interface.
+ *
+ *
+ */
+
+
+ interface GenericError {
+
+ /**
+ * \brief 16-bit error code.
+ */
+ readonly attribute unsigned short code;
+ };
+
+ /**
+ * \brief DeviceApiError error interface.
+ *
+ * The error codes must be in the range 10000-19999.
+ */
+
+ interface DeviceAPIError : GenericError {
+
+ /**
+ * \brief Unknown error.
+ */
+ const unsigned short UNKNOWN_ERROR = 10000;
+
+ /**
+ * \brief Invalid value was specified as input parameter.
+ */
+ const unsigned short INVALID_ARGUMENT_ERROR = 10001;
+
+ /**
+ * \brief The searched value or object was not found.
+ */
+ const unsigned short NOT_FOUND_ERROR = 10002;
+
+ /**
+ * \brief Operation is pending.
+ */
+ const unsigned short PENDING_OPERATION_ERROR = 10003;
+
+ /**
+ * \brief Input/Output error.
+ */
+ const unsigned short IO_ERROR = 10004;
+
+ /**
+ * \brief Not supported error.
+ */
+ const unsigned short NOT_SUPPORTED_ERROR = 10005;
+ };
+
+ /**
+ * \brief Security error interface.
+ *
+ * The error codes must be in the range 20000-29999
+ */
+ interface SecurityError : GenericError {
+ const unsigned short PERMISSION_DENIED_ERROR = 20000;
+ };
+
+ /**
+ * \brief PendingOperation.
+ *
+ * Interface that is returned by asynchronous operations in order to
+ * provide a cancellation operation.
+ */
+ interface PendingOperation {
+ /**
+ * \brief Call to cancel the underlying asynchronous operation.
+ *
+ * This call is always successful, i.e. the pending operation i.e.
+ * either cancelled or one of the callback is called.
+ *
+ * \return <em>false</em> if the cancellation did not succeed
+ * either because the pending operation finished already or because
+ * the cancellation cannot succeed due to technical limitations in
+ * the underlying implementation. Consquently the pending operation
+ * completes and depending on the success or failure the appropriate
+ * callbacks will be called.
+ * <em>true</em> if the cancellation did succeed. No callbacks will
+ * be called by the cancelled pending operation.
+ */
+ boolean cancel();
+ };
+
+ /**
+ * \brief BONDI root API.
+ * bondi root property exists in the global object
+ * \def-api-feature http://bondi.omtp.org/api/bondi.requestfeature
+ */
+ interface Bondi {
+ /**
+ * \brief Requests a feature.
+ *
+ * This function requests a named feature
+ * asynchronously and returns a pending operation object.
+ * If it succeeds it calls the successCallback and passes in
+ * the object of the requested feature. If it fails it calls
+ * the errorCallback passing in a DeviceAPIError which provides
+ * an error message and error code indicating the nature of the error.
+ *
+ * If the requested feature binds itself to a root namespace
+ * ( for example, "bondi.pim.contact") this will happen prior to the
+ * successCallback being invoked.
+ *
+ * \param successCallback the success callback function
+ * \param errorCallback the error callback function
+ * \param name the feature name IRI
+ *
+ * \return PendingOperation enabling the requester to cancel this request.
+ *
+ * The errorCallback will receive one of the following errors:
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if a malformed
+ * argument has been supplied or a required argument has been omitted.
+ * \throw DeviceAPIError NOT_FOUND_ERROR if the requested feature could not be found.
+ * \throw SecurityError PERMISSION_DENIED_ERROR if the
+ * requested feature is not permitted to load/bind or that
+ * access to a required device capability has been denied.
+ * \throw DeviceAPIError UNKNOWN_ERROR if an error occurred and a pending
+ * operation object can't be returned.
+ */
+ PendingOperation requestFeature(in RequestFeatureSuccessCallback successCallback,
+ in ErrorCallback errorCallback,
+ in DOMString name)
+ raises(DeviceAPIError, SecurityError);
+ };
+ interface BondiObject {
+ readonly attribute Bondi bondi;
+ };
+ Window implements bondiObject;
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/filesystem.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/filesystem.widl
new file mode 100644
index 000000000..35f602b85
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/filesystem.widl
@@ -0,0 +1,1038 @@
+/*
+ * Licensed to OMTP Ltd. (OMTP) under one or more contributor license agreements.
+ * See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership.
+ *
+ * The Reference Implementation (save for such parts of the reference implementation made
+ * available under separate terms and conditions) is made available under the terms of the
+ * Apache License, version 2.0, subject to the condition that any "Works" and "Derivative
+ * Works" used or distributed for commercial purposes must be and remain compliant with the
+ * BONDI specification as promulgated by OMTP in each release. Your implementation of the
+ * Reference Implementation (whether object or source) must maintain these conditions, and
+ * you must notify any recipient of this condition in a conspicuous way.
+ *
+ * You may not use this BONDI Reference Implementation except in compliance with the License.
+ *
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 or at
+ * http://bondi.omtp.org/BONDI-LICENSE-2.0
+ */
+
+/**
+ * \brief BONDI filesystem API.
+ *
+ * The BONDI filesystem API provides access to the filesystem of a device. The
+ * filesystem is abstractly represented as a collection of disjoint filesystem
+ * root locations each corresponding to some specific location in the device
+ * filesystem. The filesystem API exposes the hierarchies below these root
+ * locations as a single virtual filesystem but provides no access to other
+ * parts of the device filesystem.
+ *
+ * The roots that are exposed are determined by the platform also by the
+ * context in which the filesystem API is invoked.
+ *
+ * Each root has a string name. Each file or directory within the virtual
+ * filesystem is addressed using a fully-qualified path of the form:
+ * <em>&lt;root name&gt;/&lt;path&gt;</em> where <em>&lt;rootname&gt;</em> is
+ * the name of the root and <em>&lt;path&gt;</em> is the path to the file or
+ * directory relative to that root.
+ *
+ * The list of the supported root locations can be retrieved by calling
+ * filesystem.getRootLocations().
+ *
+ * The default location for a specific type of file, if one exists, can be
+ * obtained by calling the filesystem.getDefaultLocation(...) method. A set of
+ * platform-independent symbolic names for media types is defined. The default
+ * location for a given file type may itself be a root, or some subdirectory of
+ * a root. Although the set of roots available on a device is
+ * platform-dependent, the getDefaultLocation(...) functionality can be used to
+ * ensure that web applications can be written in a platform-independent way.
+ *
+ * In order to access specific locations which are prefixed with a value
+ * retrieved by filesystem.getDefaultLocation or some root location returned by
+ * filesystem.getRootLocations a File handle must be retrieved using the
+ * filesystem.resolve call.
+ *
+ * A File handle represents either a file or a directory. If it is a file the
+ * isFile attribute will be <em>true</em>, otherwise the isDirectory attribute
+ * will be <em>true</em>. A file can be opened for reading and writing, using a
+ * FileStream handle. A directory can be used to list its contents which is a
+ * list of files and sub-directories. There is a resolve method on directories
+ * as well in order to resolve files or sub-directories more conveniently than
+ * processing directory listings.
+ *
+ * The "/" character is used as the (path) component separator.
+ * The use of "." or ".." in location components is not required to be
+ * supported.
+ *
+ * All path characters need to be <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a> encoded.
+ *
+ * \code
+ * function errorCB(err) {
+ * alert("BONDI filesystem API couldn't be requested: " + err.message);
+ * }
+ *
+ * function successCB() {
+ * var docLocation = bondi.filesystem.getDefaultLocation("documents");
+ * var docDir = bondi.filesystem.resolve(docLocation);
+ * var docFiles = docDir.listFiles();
+ * for(var i = 0; i &lt; docFiles.length; i++) {
+ * // displays name of each image file in image directory
+ * alert(docFiles[i].name);
+ * }
+ * var testFile = docDir.createFile("test.txt");
+ * var out = testFile.open("w", "UTF-8");
+ * // writes Hello World to test.txt
+ * out.write("Hello World");
+ * out.close();
+ * }
+ *
+ * bondi.requestFeature(successCB, errorCB, "filesystem");
+ * \endcode
+ *
+ * \def-api-feature http://bondi.omtp.org/api/filesystem.read
+ * \brief Filesystem read operations, including reading directory listings,
+ * file contents and resolving root locations.
+ * \device-cap io.file.read
+ *
+ * \def-api-feature http://bondi.omtp.org/api/filesystem.write
+ * \brief Filesystem write operations, including creating files/directories,
+ * writing to files, deleting files/directories, moving and copying
+ * files.
+ * \device-cap io.file.write
+ *
+ * \def-api-feature-set http://bondi.omtp.org/api/filesystem
+ * \brief All the FileSystem features
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \def-device-cap io.file.read
+ * \brief Read directory or file
+ * \param name Name of directory or file, in virtual filesystem,
+ * e.g. rootlocation/filename
+ *
+ * \def-device-cap io.file.write
+ * \brief Write directory or file
+ * \param name Name of directory or file, in virtual filesystem,
+ * e.g. rootlocation/filename
+ *
+ * \author Paddy Byers &lt;paddy@aplixcorp.com&gt;
+ * \author Anselm R Garbe &lt;anselm@aplixcorp.com&gt;
+ * \version 1.1
+ */
+module filesystem {
+
+ /**
+ * \brief Array of File handles.
+ *
+ * This array type is returned when directory listings are requested.
+ */
+ typedef sequence<File> FileArray;
+
+ /**
+ * \brief File system specific success callback.
+ *
+ * This callback interface specifies a success callback with a function
+ * taking a File object as input argument. It is used in asynchronous
+ * operations such as copying, moving and deleting files.
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface FileSystemSuccessCallback {
+ /**
+ * \brief Method invoked when the asynchronous call completes succesfully
+ *
+ * \param file The file resulting from the asynchronous call
+ */
+ void onSuccess(in File file);
+ };
+
+ /**
+ * \brief Manager class exposed as the filesystem modules API.
+ *
+ * This manager class exposes the filesystem base API, such as
+ * determining root and default locations, resolving a given location
+ * into a File Handle and registering filesystem listeners for
+ * filesystem events.
+ *
+ * \code
+ * function errorCB(err) {
+ * alert("BONDI filesystem API couldn't be requested: " + err.message);
+ * }
+ *
+ * function successCB() {
+ * var docLocation = bondi.filesystem.getDefaultLocation("documents");
+ * var docDir = bondi.filesystem.resolve(docLocation);
+ * var docFiles = docDir.listFiles();
+ * for(var i = 0; i &lt; docFiles.length; i++) {
+ * // displays name of each image file in image directory
+ * alert(docFiles[i].name);
+ * }
+ * var testFile = docDir.createFile("test.txt");
+ * var out = testFile.open("w", "UTF-8");
+ * // writes Hello World to test.txt
+ * out.write("Hello World");
+ * out.close();
+ * }
+ *
+ * bondi.requestFeature(successCB, errorCB, "filesystem");
+ * \endcode
+ */
+ interface FileSystemManager {
+
+ /**
+ * \brief Contains the platform-dependent maximum path length.
+ *
+ * Read-only.
+ *
+ * \code
+ * alert(bondi.filesystem.maxPathLength);
+ * \endcode
+ */
+ readonly attribute unsigned long maxPathLength;
+
+ /**
+ * \brief Returns a default location path for the given arguments,
+ * including the root location prefix.
+ *
+ * Optionally this method can be called with the space argument
+ * specifying the minimum free disk space required.
+ *
+ * This function resolves location specifiers to location paths.
+ * The following location specifiers are supported:
+ * \n "wgt:package" the widget package location
+ * \n "wgt:private" the widgets private storage
+ * \n "wgt:public" the widgets public storage
+ * \n "wgt:temp" the widgets temporary storage
+ * \n "documents" the documents location,
+ * e.g. the "My Documents" directory on some systems
+ * \n "images" the images location,
+ * e.g. the "My Pictures" directory on some systems
+ * \n "videos" the videos location,
+ * e.g. the "My Videos" directory on some systems
+ * \n "temp" the temporary storage,
+ * e.g resolving to "Temp"
+ * \n "sdcard" the sdcard storage, if any
+ *
+ * \code
+ * var wgtLocation = bondi.filesystem.getDefaultLocation('wgt:package');
+ * \endcode
+ *
+ * \param specifier the location specifier, see above for supported specifiers.
+ * \param minFreeSpace optional, minimum required free disk space in bytes for
+ * this location, <em>0</em> (default) means no limitation
+ * \return the location as a string or <em>null</em> if there
+ * is no location for the given specifier or if there is not
+ * enough space left for the requested space in bytes.
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if the
+ * specifier or space arguments are invalid
+ */
+ DOMString getDefaultLocation(in DOMString specifier, in unsigned long minFreeSpace)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Returns all root locations.
+ *
+ * The root locations are symbolic names for filesystem
+ * locations which are accessible and supported by the
+ * underlying platform.
+ *
+ * Usually the following root locations will be supported:
+ * \n "documents" represents "My Documents" on some platforms
+ * \n "images" represents "My Pictures" on some platforms
+ * \n "videos" represents "My Videos" on some platforms
+ * \n "temp" represents "tmp" on some platforms
+ * \n "sdcard" represents the sdcard on some platforms
+ *
+ * See also the getDefaultLocation method.
+ *
+ * \code
+ * var locations = bondi.filesystem.getRootLocations();
+ * for(var i = 0; i &lt; locations.length; i++) {
+ * // locations[i] is a resolvable root location
+ * }
+ * \endcode
+ *
+ * \return string array of root locations.
+ */
+ StringArray getRootLocations();
+
+ /**
+ * \brief Resolves a location to a File handle.
+ *
+ * Validates and resolves the given location to a File handle
+ * and returns a handle. A valid location is prefixed with a
+ * valid root or default location and must address an existing
+ * and accessible file.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var location = bondi.filesystem.getDefaultLocation("temp");
+ * var temp = bondi.filesystem.resolve(location);
+ * var documents = bondi.filesystem.getDefaultLocation("documents");
+ * var mydoc = bondi.filesystem.resolve(documents + "/data/2009/mydoc.txt");
+ * \endcode
+ *
+ * \param location the location to resolve. Must be absolute
+ * prefixed by a valid root or default location.
+ * \return the resolved file object.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if invalid location was given.
+ */
+ File resolve(in DOMString location)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Registers a filesystem event listener.
+ *
+ * Filesystem event listeners are used in order to retrieve
+ * notifications if root or default locations such as storage
+ * cards are mounted/unmounted into/from the device filesystem.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var listener = { mountEvent: function(location) { alert('mounted ' + location); },
+ * unmountEvent: function(location) { alert('unmounted ' + location); };
+ * bondi.filesystem.registerEventListener(listener);
+ * \endcode
+ *
+ * \param listener the listener interface implementation
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if the given listener
+ * is invalid or not a listener.
+ */
+ void registerEventListener(in FileSystemListener listener)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Unregisters a filesystem event listener.
+ *
+ * \code
+ * bondi.filesystem.unregisterEventListener(listener);
+ * \endcode
+ *
+ * \param listener the listener interface implementation
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if the given listener
+ * is invalid or not a listener.
+ */
+ void unregisterEventListener(in FileSystemListener listener)
+ raises(DeviceAPIError);
+ };
+
+ /**
+ * \brief Filesystem event listener class.
+ *
+ * This listener implements two methods to retrieve mount and unmount
+ * notifications if root or default locations on a storage card get
+ * available or unavailable.
+ *
+ * \code
+ * var fsEventImpl = {
+ * mountEvent: function(location) {
+ * // location has been mounted
+ * },
+ * unmountEvent: function(location) {
+ * // location has been unmounted
+ * }
+ * };
+ * \endcode
+ */
+ interface FileSystemListener {
+
+ /**
+ * \brief Called when a new root location gets available.
+ *
+ * A new location could be a storage card for example.
+ *
+ * \param location the newly available location
+ */
+ void mountEvent(in DOMString location);
+
+ /**
+ * \brief Called when a location gets unavailable.
+ *
+ * Such a location could be a storage card for example.
+ *
+ * \param location the location which is becoming unavailable
+ */
+ void unmountEvent(in DOMString location);
+ };
+
+ /**
+ * \brief File class.
+ *
+ * This interface represents the file abstraction in use. A file handle
+ * can address files or directories. A file handle represents a file
+ * if the isFile property is <em>true</em>, otherwise it represents a
+ * directory.
+ *
+ * A file handle representing a file can be opened for I/O operations
+ * such as reading and writing.
+ *
+ * A file handle representing a directory can list all files in the
+ * current directory.
+ *
+ * \code
+ *
+ * // list directory contents
+ * var files = dir.listFiles();
+ * for(var i = 0; i &lt; files.length; i++) {
+ * // alerts each name of dir's contents
+ * alert(files[i].name);
+ * }
+ *
+ * // opens a file for writing
+ * var file = dir.createFile("test.txt");
+ * var out = file.open("w", "UTF-8");
+ * // writes Hello World to test.txt
+ * out.write("Hello World");
+ * out.close();
+ * \endcode
+ */
+ interface File {
+
+ /**
+ * \brief Parent directory handle.
+ *
+ * Read-only.
+ *
+ * <em>null</em> if there is no parent directory.
+ *
+ * If there is no parent directory, this represents a root location.
+ *
+ * \code
+ * var parent = file.parent;
+ * if(parent != null) {
+ * // parent directory handle
+ * }
+ * \endcode
+ */
+ readonly attribute File parent;
+
+ /**
+ * \brief File/directory access state in the filesystem.
+ *
+ * Read-only.
+ *
+ * <em>false</em> if there is write access.
+ *
+ * This attribute represents the actual state of a
+ * file/directory in the filesystem. It does not check if the
+ * accessor has io.file.write permission.
+ *
+ * \code
+ * if(file.readOnly) {
+ * // file cannot be written
+ * }
+ * \endcode
+ */
+ readonly attribute boolean readOnly;
+
+ /**
+ * \brief File type.
+ *
+ * Read-only.
+ *
+ * <em>true</em> if this handle is a file.
+ * <em>false</em> if this handle is a directory.
+ *
+ * \code
+ * if(file.isFile) {
+ * // is a file
+ * }
+ * \endcode
+ */
+ readonly attribute boolean isFile;
+
+ /**
+ * \brief File type.
+ *
+ * Read-only.
+ *
+ * <em>true</em> if this handle is a directory.
+ * <em>false</em> if this handle is a file.
+ *
+ * \code
+ * if(file.isDirectory) {
+ * // is a directory
+ * }
+ * \endcode
+ */
+ readonly attribute boolean isDirectory;
+
+ /**
+ * \brief Creation timestamp.
+ *
+ * Read-only.
+ *
+ * The creation timestamp of this file. This is the timestamp
+ * when the file was first created in the filesystem. This is
+ * equivalent to the timestamp when a call to createFile()
+ * succeeds.
+ *
+ * It is unspecified and platform-dependent if the creation
+ * timestamp changes when a file is moved.
+ *
+ * \code
+ * alert(file.created); // displays the creation timestamp
+ * \endcode
+ *
+ */
+ readonly attribute Date created;
+
+ /**
+ * \brief Modification timestamp.
+ *
+ * Read-only.
+ *
+ * The modification timestamp of this file. This is the timestamp
+ * of the most recent modification to the file, usually when the last
+ * write operation succeeded. Opening a file for reading does not change
+ * the modification timestamp.
+ *
+ * \code
+ * alert(file.modified); // displays the modification timestamp
+ * \endcode
+ *
+ */
+ readonly attribute Date modified;
+
+ /**
+ * \brief Path of this file, excluding the file name.
+ *
+ * Read-only.
+ *
+ * If the file path is <em>/baz/foo.bar</em>, then
+ * the path is <em>/baz/</em>.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \code
+ * alert(file.path); // should be /baz/ if the file is /baz/foo.bar
+ * \endcode
+ */
+ readonly attribute DOMString path;
+
+ /**
+ * \brief File name, excluding any path components.
+ *
+ * Read-only.
+ *
+ * Assumed the file path is <em>/baz/foo.bar</em>, then
+ * the file name is <em>foo.bar</em>.
+ *
+ * The encoding of file names is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \code
+ * alert(file.name); // should be foo.bar if the file path is /baz/foo.bar
+ * \endcode
+ */
+ readonly attribute DOMString name;
+
+ /**
+ * \brief Absolute path of this file.
+ *
+ * Read-only.
+ *
+ * Assumed the file path is <em>/baz/foo.bar</em>, then this is the absolute path.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \code
+ * alert(file.absolutePath); // should be /baz/foo.bar if the file is /baz/foo.bar
+ * \endcode
+ */
+ readonly attribute DOMString absolutePath;
+
+ /**
+ * \brief Size in bytes of this file.
+ *
+ * Read-only.
+ *
+ * If it is attempted to read this attribute on a directory,
+ * <em>undefined</em> is returned.
+ *
+ * \code
+ * alert(file.fileSize); // displays the file size
+ * \endcode
+ */
+ readonly attribute unsigned long fileSize;
+
+ /**
+ * \brief Files metadata.
+ *
+ * The actual map contents are implementation dependent.
+ *
+ * \code
+ * // should display the file author, if supported by the
+ * // platform, undefined otherwise
+ * alert(file.metadata.author);
+ * \endcode
+ */
+ readonly attribute Map metadata;
+
+ /**
+ * \brief Returns list of all files of this directory.
+ *
+ * The list of files contains directories and files, it does
+ * not contain the directories "." and "..".
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var files = dir.listFiles();
+ * for(var i = 0; i &lt; files.length; i++) {
+ * // files[i] iterate over all files of this directory
+ * }
+ * \endcode
+ *
+ * \return array of contents of this directory.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ */
+ FileArray listFiles()
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Opens the file in the given mode supporting the given
+ * encoding.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * // opens file for reading
+ * var in = file.open("r", "UTF-8");
+ * \endcode
+ *
+ * \param mode the mode for opening a file
+ * \n "r" for reading
+ * \n "a" for appending
+ * \n "w" for [over]writing
+ * \param encoding the encoding for read/write operations on the file,
+ * supported encodings are:
+ * \n "<a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>" default encoding
+ * \n "<a href="http://en.wikipedia.org/wiki/ISO/IEC_8859-1">ISO8859-1</a>" latin1 encoding
+ * \return file stream handle to read/write from/to.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if invalid mode
+ * or unsupported encoding is supplied.
+ * \throw DeviceAPIError IO_ERROR if this is not a file.
+ */
+ FileStream open(in DOMString mode, in DOMString encoding)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Copies this file.
+ *
+ * The copy will be created in the given path. If this function
+ * fails and the error callback is called, it will pass an
+ * DeviceAPIError IO_ERROR to the callback.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * // copies this file to /temp/file.copy
+ * var op = file.copyTo(function(copiedFile) { alert("file copied"); }, null, "/temp/file.copy", false);
+ * \endcode
+ *
+ * \param successCallback called when the file has been copied.
+ * \param errorCallback called if an error occured.
+ * \param filePath the new file path, [a-Z0-9_- /]+ are allowed
+ * \param overwrite <em>true</em> enforces overwriting an existing file.
+ * \return PendingOperation enabling the requester to cancel this request.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if it is attempted to move to a directory.
+ * \throw DeviceAPIError IO_ERROR if overwrite is <em>false</em> and target file exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be copied.
+ */
+ PendingOperation copyTo(in FileSystemSuccessCallback successCallback,
+ in ErrorCallback errorCallback,
+ in DOMString filePath,
+ in boolean overwrite)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Moves this file.
+ *
+ * The file will be moved atomically to the given path. This is
+ * different to copyTo and deleting the old file, because this
+ * operation does not need extra disk space on certain platforms.
+ * If this function fails and the error callback is called, it
+ * will pass an DeviceAPIError IO_ERROR to the callback.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * // moves this file to /temp/file.move
+ * var op = file.moveTo(function(movedFile) { file = movedFile; }, null, "/temp/file.move");
+ * \endcode
+ *
+ * \param successCallback called when the file has been copied.
+ * \param errorCallback called if an error occured.
+ * \param filePath the new file name, [a-Z0-9_- /]+ are allowed
+ * \param overwrite <em>true</em> enforces overwriting an existing file.
+ * \return PendingOperation enabling the requester to cancel this request.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if it is attempted to move to a directory.
+ * \throw DeviceAPIError IO_ERROR if overwrite is <em>false</em> and target file exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be moved.
+ */
+ PendingOperation moveTo(in FileSystemSuccessCallback successCallback,
+ in ErrorCallback errorCallback,
+ in DOMString filePath,
+ in boolean overwrite)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Creates a directory.
+ *
+ * The new directory will be created relatively to the current
+ * directory this operation is performed on. It will attempt to
+ * create all necessary sub-directories as well. The use of "."
+ * or ".." in path components is not supported. If the
+ * bottom-most directory being created already exists this
+ * method will throw an IO_ERROR.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var newDir = dir.createDirectory("newDir");
+ * var anotherNewDir = dir.createDirectory("newDir1/subNewDir1");
+ * \endcode
+ *
+ * \param dirPath the new directory path, it should only contain
+ * characters supported by the underlying filesystem.
+ * \return file handle of the new directory
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ * \throw DeviceAPIError IO_ERROR if any path component does not exist.
+ * \throw DeviceAPIError IO_ERROR if a file with the same name exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the directory cannot be created.
+ */
+ File createDirectory(in DOMString dirPath)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Creates a new empty file.
+ *
+ * The new empty file is created in the given path relatively
+ * to the current directory the operation is performed on. The
+ * use of "." or ".." in path components is not supported. If
+ * the bottom-most file being created already exists this
+ * method will throw an IO_ERROR. If any path component does
+ * not exist this method will throw an IO_ERROR.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var newFile = dir.createFile("newFile");
+ * \endcode
+ *
+ * \param filePath the new file path, it should only contain
+ * characters supported by the underlying filesystem.
+ * \return file handle of the new empty file
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ * \throw DeviceAPIError IO_ERROR if any path component does not exist.
+ * \throw DeviceAPIError IO_ERROR if the file already exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be created.
+ */
+ File createFile(in DOMString filePath)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Resolves an existing file or directory relatively to
+ * the current directory this operation is performed on; and
+ * returns a file handle for it.
+ *
+ * The filePath is not allowed to contain the "." or ".." directories.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var hellofile = dir.resolve("foo/hello.txt");
+ * \endcode
+ *
+ * \param filePath the relative file/directory path to resolve.
+ * \return file handle of the file or <em>null</em> if it cannot be resolved.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file or directory cannot be resolved.
+ */
+ File resolve(in DOMString filePath)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Deletes this directory.
+ *
+ * This function attempts to delete a directory or directory
+ * tree synchronously and returns <em>true</em> on success,
+ * <em>false</em> otherwise. It may throw an IO_ERROR if a
+ * recursive deletion partially fails and any deleted data so
+ * far cannot be recovered. This might happen due the lack of
+ * filesystem permissions or if any directories or files are
+ * openened by other processes.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var fullPath = dir.fullPath;
+ * if(dir.deleteDirectory(true)) {
+ * // subsequent accesses to dir will throw an error
+ * alert(fullPath + ' deleted');
+ * }
+ * \endcode
+ *
+ * \param recursive <em>true</em> means a recursive deletion, this
+ * will destroy all data recursively, use with caution.
+ * \return <em>true</em> on success
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is a file.
+ * \throw DeviceAPIError IO_ERROR if the directory is not empty and
+ * this operation is not performed recursively.
+ * \throw DeviceAPIError IO_ERROR if the directory or any file or sub-directory cannot be deleted.
+ */
+ boolean deleteDirectory(in boolean recursive)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Deletes this file.
+ *
+ * Returns <em>true</em> on success, <em>false</em> otherwise.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var fullPath = dir.fullPath;
+ * if(dir.deleteFile()) {
+ * // subsequent accesses to dir will throw an error
+ * alert(fullPath + ' deleted');
+ * }
+ * \endcode
+ *
+ * \return <em>true</em> on success
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is a directory.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be deleted due
+ * the lack of filesystem permissions or if it is locked or
+ * opened by another process.
+ */
+ boolean deleteFile()
+ raises(SecurityError, DeviceAPIError);
+ };
+
+ /**
+ * \brief FileStream API.
+ *
+ * A FileStream represents a handle to a File opened for read and/or
+ * write operations. Read and write operations are performed relative
+ * to a file pointer which represents the current position in the file.
+ *
+ * A series of read/write methods are available that permit both binary and
+ * text to be processed.
+ *
+ * Once a file stream is closed, any operation attempted on this stream
+ * will result in a normal JavaScript error.
+ */
+ interface FileStream {
+
+ /**
+ * \brief Indicates whether or not the current file pointer is at the end
+ * of the file.
+ *
+ * <em>true</em> if the position is at the end of the current file stream.
+ *
+ * \code
+ * if(stream.eof) {
+ * // file has been read completely
+ * }
+ * \endcode
+ */
+ readonly attribute boolean eof;
+
+ /**
+ * \brief Get/set stream position for reads/writes.
+ *
+ * The stream position is an offset of bytes from the start of
+ * the file stream. When invoking an operation that reads or
+ * writes from the stream, the operation will take place from
+ * the position in the position attribute.
+ *
+ * \code
+ * alert(stream.position); // displays current stream position
+ * // alters current stream position to the begin of the file,
+ * // like seek() in C
+ * stream.position = 0;
+ * \endcode
+ * \throw DeviceAPIError IO_ERROR if a position was given that is out of the stream range.
+ */
+ attribute unsigned long position
+ setraises(DeviceAPIError);
+
+ /**
+ * \brief Returns the number of bytes that are available for
+ * reading from the stream.
+ *
+ * The number of bytes available for reading is the maximum
+ * amount of bytes that can be read in the next read operation.
+ *
+ * -1 if eof is <em>true</em>.
+ *
+ * \code
+ * alert(stream.bytesAvailable); // displays the available bytes to be read
+ * \endcode
+ */
+ readonly attribute unsigned long bytesAvailable;
+
+ /**
+ * \brief Closes this FileStream.
+ *
+ * Flushes any pending buffered writes and closes the File. Always succeeds.
+ * Note that pending writes might not succeed.
+ *
+ * \code
+ * stream.close(); // closes this stream, no subsequent access to stream allowed
+ * \endcode
+ */
+ void close();
+
+ /**
+ * \brief Reads the specified number of characters.
+ *
+ * Reads specified number of characters and returns them as string.
+ * The resulting string length might be shorter than charCount if eof
+ * is <em>true</em>.
+ *
+ * \code
+ * var text = stream.read(0);
+ * stream.close();
+ * \endcode
+ *
+ * \param charCount number of characters being read, if
+ * <em>0</em> it will read as long as bytes are available.
+ * \return the result of read characters as a string.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during read.
+ */
+ DOMString read(in unsigned long charCount)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Reads the specified number of bytes from this FileStream.
+ *
+ * If 0 is supplied it will read all available bytes in a
+ * single read operation.
+ *
+ * \code
+ * // reads up to 256 bytes from the stream
+ * var raw = stream.readBytes(256);
+ * for(var i = 0; i &lt; raw.length; i++) {
+ * // raw[i] contains the i-th byte of the current data chunk
+ * }
+ * \endcode
+ *
+ * \param byteCount number of bytes being read. Must not be <em>0</em>.
+ * \return the result of read bytes as a byte (or number) array.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during readBytes.
+ */
+ ByteArray readBytes(in unsigned long byteCount)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Reads the specified number of bytes from this FileStream, encoding
+ * the result in base64.
+ *
+ * If 0 is supplied it will read all available bytes in a
+ * single read operation.
+ *
+ * \code
+ * // reads up to 256 bytes from the stream
+ * var base64 = stream.readBase64(256);
+ * \endcode
+ *
+ * \param byteCount number of bytes being read. Must not be <em>0</em>.
+ * \return the result of read bytes as base64 encoding string.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during readBase64.
+ */
+ DOMString readBase64(in unsigned long byteCount)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Writes the specified DOMString to this FileStream.
+ *
+ * \code
+ * var text = "Hello world";
+ * stream.write(text);
+ * \endcode
+ *
+ * \param stringData the actual string to be written.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during write.
+ */
+ void write(in DOMString stringData)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Writes the specified bytes to this FileStream.
+ *
+ * \code
+ * var bytes = in.readBytes(256);
+ * out.writeBytes(bytes); // writes the bytes read from in to out
+ * \endcode
+ *
+ * \param byteData the byte data array being written.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during writeBytes.
+ */
+ void writeBytes(in ByteArray byteData)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Converts the specified base64 DOMString to bytes and writes the
+ * result to this FileStream.
+ *
+ * \code
+ * var base64 = in.readBase64(256);
+ * out.writeBase64(base64); // writes the base64 data read from in to out
+ * \endcode
+ *
+ * \param base64Data the base64 data being written.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during writeBase64.
+ */
+ void writeBase64(in DOMString base64Data)
+ raises(DeviceAPIError);
+ };
+
+ /**
+ * \brief Specifies what is instantiated at feature request
+ * \def-instantiated
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ */
+ interface FileSystemManagerObject {
+ readonly attribute FileSystemManager fileSystemManager;
+ };
+ bondi implements FileSystemManagerObject;
+
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl
new file mode 100644
index 000000000..442527709
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--====================================================================
+$Id$
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+XSLT stylesheet to extract Web IDL snippets from Web IDL spec.
+=====================================================================-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="text" encoding="utf-8"/>
+
+<xsl:template match="code[@class='idl-code']">
+ <xsl:value-of select="."/><xsl:text>
+</xsl:text>
+</xsl:template>
+
+<xsl:template match="text()"/>
+
+</xsl:stylesheet>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/widlhtml.css b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/widlhtml.css
new file mode 100644
index 000000000..8543097a3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/examples/widlhtml.css
@@ -0,0 +1,100 @@
+body {
+ padding: 2em;
+ margin: 0;
+ font-family: sans-serif;
+ color: black;
+ background: white;
+ background-position: top left;
+ background-attachment: fixed;
+ background-repeat: no-repeat;
+}
+:link { color: #00C; background: transparent }
+:visited { color: #609; background: transparent }
+a:active { color: #C00; background: transparent }
+a:link img, a:visited img { border-style: none } /* no border on img links */
+
+h1, h2, h3, h4, h5, h6 { text-align: left }
+/* background should be transparent, but WebTV has a bug */
+h1, h2, h3 { color: #009393; background: white }
+h1 { font: 170% sans-serif }
+h2 { font: 140% sans-serif }
+h3 { font: 120% sans-serif }
+h4 { font: bold 100% sans-serif }
+h5 { font: italic 100% sans-serif }
+h6 { font: small-caps 100% sans-serif; margin-bottom: 0 }
+
+.hide { display: none }
+
+code { font-size: 120% }
+
+ul.toc, ol.toc, ul.authors {
+ list-style: none;
+}
+
+.hide { display: none }
+
+div.head { margin-bottom: 1em }
+div.head h1 { margin-top: 2em; clear: both }
+div.head table { margin-left: 2em; margin-top: 2em }
+div.constraint, div.issue, div.note, div.notice { margin-left: 2em; }
+div.exampleInner pre { margin-left: 1em; margin-top: 0em; margin-bottom: 0em}
+div.exampleOuter {border: 4px double gray; margin: 0em; padding: 0em}
+div.exampleInner { background-color: #d5dee3;
+ border-top-width: 4px;
+ border-top-style: double;
+ border-top-color: #d3d3d3;
+ border-bottom-width: 4px;
+ border-bottom-style: double;
+ border-bottom-color: #d3d3d3;
+ padding: 4px; margin: 0em }
+div.exampleWrapper { margin: 4px }
+div.exampleHeader { font-weight: bold; margin: 4px}
+div.term { font: 100% sans-serif; color:#000000; font-weight: bold; line-height: 60%}
+div.list { font: 100% sans-serif; color:#000000; font-weight: normal; line-height: 60%}
+
+.optional {text-decoration: line-through; display: none;}
+
+.copyright,.legalnotice { font-size: small }
+.copyright small { font-size: small }
+
+@media screen { /* hide from IE3 */
+a[href]:hover { background: #ffa }
+}
+
+ol.enumar { list-style-type: decimal; }
+ol.enumla { list-style-type: lower-alpha; }
+ol.enumlr { list-style-type: lower-roman; }
+ol.enumua { list-style-type: upper-alpha; }
+ol.enumur { list-style-type: upper-roman; }
+
+/* BONDI additions */
+
+.toc {
+ list-style-type: none;
+}
+
+pre {
+ background-color:#D5DEE3;
+ overflow: auto;
+ padding: 1em;
+}
+
+.examplecode {
+ background-color: #EEE;
+}
+
+.def-api-feature-set dt, .def-api-feature dt, dt .def-device-cap, dt.const code { font: bold 100% sans-serif; }
+dt.attribute code, dt.method code { font: italic 100% sans-serif; }
+
+.def-device-caps dd { margin-bottom: 2em }
+
+dt.method { margin-top: 2em }
+
+.summary td {
+ text-align: left;
+ background-color: #BBDDDD;
+ color: inherit;
+ font-family: monospace;
+ white-space:pre;
+ padding: .3em 1em .3em 1em;
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.c b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.c
new file mode 100644
index 000000000..622a7bea7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.c
@@ -0,0 +1,1827 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "comment.h"
+#include "entities.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "os.h"
+#include "process.h"
+
+/* struct cnode : a node in the comment parse tree */
+struct cnode {
+ struct cnode *next;
+ struct cnode *children;
+ struct cnode *parent;
+ const struct cnodefuncs *funcs;
+ const char *attrtext;
+ const char *filename;
+ unsigned int linenum;
+};
+
+struct cnodefuncs {
+ int indesc; /* non-zero if it outputs its own xml element that does
+ not want to be inside <description> */
+ int needpara; /* non-zero if text must be in a para node that is a child
+ of this one */
+ int (*askend)(struct cnode *cnode, const struct cnodefuncs *type);
+ void (*end)(struct cnode *cnode);
+ void (*output)(struct cnode *cnode, unsigned int indent);
+};
+
+struct paramcnode {
+ struct cnode cn;
+ int inout;
+ char name[1];
+};
+
+/* struct comment : a doxygen comment */
+struct comment {
+ struct comment *next;
+ struct node *node;
+ unsigned int type;
+ const char *filename;
+ unsigned int linenum;
+ struct cnode root;
+ int back; /* Whether the comment refers back rather than forward. */
+ char *text;
+};
+
+
+static struct node *lastidentifier;
+static struct comment *comments;
+static int incode, inhtmlblock;
+static struct comment *curcomment;
+
+/***********************************************************************
+ * htmleldescs : table of recnogized HTML elements
+ */
+#define HTMLEL_EMPTY 1
+#define HTMLEL_INLINE 2
+#define HTMLEL_BLOCK 4
+#define HTMLEL_AUTOCLOSE 8
+#define HTMLEL_LI 0x10
+#define HTMLEL_DLCONTENTS 0x20
+#define HTMLEL_TABLECONTENTS 0x40
+#define HTMLEL_TRCONTENTS 0x80
+
+#define HTMLEL_FLOW (HTMLEL_BLOCK | HTMLEL_INLINE)
+
+struct htmleldesc {
+ unsigned int namelen;
+ const char *name;
+ unsigned int flags;
+ unsigned int content;
+};
+
+static const struct htmleldesc htmleldescs[] = {
+ { 1, "a", HTMLEL_INLINE, 0 },
+ { 1, "b", HTMLEL_INLINE, 0 },
+ { 2, "br", HTMLEL_INLINE, HTMLEL_EMPTY },
+ { 3, "img", HTMLEL_INLINE, HTMLEL_EMPTY },
+ { 2, "dd", HTMLEL_DLCONTENTS, HTMLEL_FLOW },
+ { 2, "dl", HTMLEL_BLOCK, HTMLEL_DLCONTENTS },
+ { 2, "dt", HTMLEL_DLCONTENTS, HTMLEL_INLINE },
+ { 2, "em", HTMLEL_INLINE, 0 },
+ { 2, "li", HTMLEL_LI, HTMLEL_FLOW },
+ { 2, "ol", HTMLEL_BLOCK, HTMLEL_LI },
+ { 1, "p", HTMLEL_BLOCK, HTMLEL_INLINE },
+ { 2, "td", HTMLEL_TRCONTENTS | HTMLEL_AUTOCLOSE, HTMLEL_FLOW },
+ { 2, "th", HTMLEL_TRCONTENTS | HTMLEL_AUTOCLOSE, HTMLEL_FLOW },
+ { 2, "tr", HTMLEL_TABLECONTENTS | HTMLEL_AUTOCLOSE, HTMLEL_TRCONTENTS },
+ { 5, "table", HTMLEL_BLOCK, HTMLEL_TABLECONTENTS },
+ { 2, "ul", HTMLEL_BLOCK, HTMLEL_LI },
+ { 0, 0, 0, 0 }
+};
+#define HTMLELDESC_B (htmleldescs + 1)
+#define HTMLELDESC_BR (htmleldescs + 2)
+
+/***********************************************************************
+ * addcomment : add a comment to the list of comments if it has doxygen syntax
+ *
+ * Enter: tok struct
+ */
+void
+addcomment(struct tok *tok)
+{
+ if (tok->len >= 1 && (tok->start[0] == '!'
+ || (tok->type == TOK_BLOCKCOMMENT && tok->start[0] == '*')
+ || (tok->type == TOK_INLINECOMMENT && tok->start[0] == '/')))
+ {
+ struct comment *comment;
+ comment = memalloc(sizeof(struct comment));
+ comment->text = memalloc(tok->len + 1);
+ memcpy(comment->text, tok->start, tok->len);
+ comment->text[tok->len] = 0;
+ comment->type = tok->type;
+ comment->filename = tok->filename;
+ comment->linenum = tok->linenum;
+ comment->node = 0;
+ comment->back = 0;
+ if (comment->text[1] == '<') {
+ comment->back = 1;
+ if (!lastidentifier) {
+ locerrorexit(comment->filename, comment->linenum,
+ "no identifier to attach doxygen comment to");
+ }
+ comment->node = lastidentifier;
+ }
+ comment->next = comments;
+ comments = comment;
+ }
+}
+
+/***********************************************************************
+ * setcommentnode : set parse node to attach comments to
+ *
+ * Enter: node2 = parse node for identifier
+ */
+void
+setcommentnode(struct node *node2)
+{
+ struct comment *comment = comments;
+ while (comment && !comment->node) {
+ comment->node = node2;
+ comment = comment->next;
+ }
+ lastidentifier = node2;
+}
+
+/***********************************************************************
+ * joininlinecomments : join adjacent inline comments
+ *
+ * Enter: comment = list of comment structs
+ *
+ * Return: new list of comment structs
+ *
+ * This function also discards any single inline comment that does not
+ * refer back.
+ */
+static struct comment *
+joininlinecomments(struct comment *comments)
+{
+ struct comment **pcomment;
+ pcomment = &comments;
+ for (;;) {
+ struct comment *comment;
+ comment = *pcomment;
+ if (!comment)
+ break;
+ if (comment->type != TOK_INLINECOMMENT) {
+ /* Keep block comment as is. */
+ pcomment = &comment->next;
+ } else if (!comment->back && (!comment->next
+ || comment->next->type != TOK_INLINECOMMENT
+ || comment->next->filename != comment->filename
+ || comment->next->linenum != comment->linenum + 1))
+ {
+ /* Discard single // comment that does not refer back. */
+ *pcomment = comment->next;
+
+ } else {
+ /* Find sequence of adjacent // comments (adjacent lines,
+ * referring to same node) and join them. We do this in two
+ * passes, one to count the length of the comment and one
+ * to join. Note that the list is still in reverse order,
+ * so we expect the line number to decrease by 1 each time. */
+ struct comment *newcomment = 0, *comment2;
+ const char *filename = comment->filename;
+ unsigned int linenum = comment->linenum;
+ for (;;) {
+ char *wp = newcomment->text;
+ comment2 = comment;
+ do {
+ unsigned int len = strlen(comment2->text);
+ if (newcomment)
+ memcpy(wp, comment2->text, len);
+ wp += len;
+ linenum--;
+ comment2 = comment2->next;
+ } while (comment2 && comment2->filename == filename
+ && comment2->linenum == linenum
+ && comment2->node == comment->node);
+ /* Finished a pass. */
+ if (newcomment) {
+ *wp = 0;
+ break;
+ }
+ newcomment = memalloc(sizeof(struct comment)
+ + wp - newcomment->text);
+ newcomment->node = comment->node;
+ newcomment->type = comment->type;
+ newcomment->filename = filename;
+ newcomment->linenum = linenum + 1;
+ }
+ /* Replace the scanned comment struct with newcomment in the
+ * list. */
+ newcomment->next = comment2;
+ *pcomment = newcomment;
+ pcomment = &newcomment->next;
+ }
+ }
+ return comments;
+}
+
+/***********************************************************************
+ * outputchildren : call output recursively on children of cnode
+ *
+ * Enter: cnode
+ * indent = indent (nesting) level of parent
+ * indesc = whether already in <description> or other top-level
+ * descriptive element
+ */
+static void
+outputchildren(struct cnode *cnode, unsigned int indent, int indesc)
+{
+ int curindesc = indesc;
+ cnode = cnode->children;
+ while (cnode) {
+ if (curindesc != cnode->funcs->indesc) {
+ assert(!indesc);
+ printf("%*s<%sdescription>\n", indent + 1, "", curindesc ? "/" : "");
+ curindesc = !curindesc;
+ }
+ (*cnode->funcs->output)(cnode, indent + 2);
+ cnode = cnode->next;
+ }
+ if (curindesc != indesc)
+ printf("%*s<%sdescription>\n", indent + 1, "", curindesc ? "/" : "");
+}
+
+/***********************************************************************
+ * default_askend : ask node if it wants to end at a para start (default
+ * implementation)
+ *
+ * Enter: cnode
+ * type = 0 else cnodefuncs for newly starting para
+ *
+ * Return: non-zero if this node wants to end
+ */
+static int
+default_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ return 1;
+}
+
+/***********************************************************************
+ * root_askend : ask root node if it wants to end at a para start
+ *
+ * Enter: cnode for root
+ * type = 0 else cnodefuncs for newly starting para
+ *
+ * Return: non-zero if this node wants to end
+ */
+static int
+root_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ return 0;
+}
+
+/***********************************************************************
+ * root_output : output root cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+root_output(struct cnode *cnode, unsigned int indent)
+{
+ outputchildren(cnode, indent, 0);
+}
+
+/***********************************************************************
+ * cnode type root
+ */
+static const struct cnodefuncs root_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &root_askend,
+ 0, /* end */
+ &root_output,
+};
+
+/***********************************************************************
+ * endcnode : end current cnode
+ *
+ * Enter: cnode = current cnode
+ *
+ * Return: cnode = new current code (parent of old one)
+ */
+static struct cnode *
+endcnode(struct cnode *cnode)
+{
+ if (cnode->funcs->end)
+ (*cnode->funcs->end)(cnode);
+ /* Reverse the children list. */
+ {
+ struct cnode *child = cnode->children;
+ cnode->children = 0;
+ while (child) {
+ struct cnode *next = child->next;
+ child->next = cnode->children;
+ cnode->children = child;
+ child = next;
+ }
+ }
+ return cnode->parent;
+}
+
+/***********************************************************************
+ * endspecificcnode : end a specific type of cnode
+ *
+ * Enter: cnode = current cnode
+ * type = type of node to end
+ * filename, linenum = filename and line number (for error reporting)
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+endspecificcnode(struct cnode *cnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum)
+{
+ while (cnode->funcs != type) {
+ if (cnode->funcs == &root_funcs)
+ locerrorexit(filename, linenum, "unmatched \\endcode");
+ cnode = endcnode(cnode);
+ }
+ return cnode;
+}
+
+/***********************************************************************
+ * startcnode : start a newly created cnode
+ *
+ * Enter: cnode = current cnode
+ * newcnode = new cnode to start
+ *
+ * Return: new current cnode (which is the same as newcnode)
+ */
+static struct cnode *
+startcnode(struct cnode *cnode, struct cnode *newcnode)
+{
+ newcnode->parent = cnode;
+ newcnode->next = cnode->children;
+ cnode->children = newcnode;
+ return newcnode;
+}
+
+/***********************************************************************
+ * para_output : output para cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+para_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<p>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</p>\n", indent, "");
+}
+
+/***********************************************************************
+ * para_end : end a para cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+para_end(struct cnode *cnode)
+{
+ /* If the para cnode is empty, remove it. */
+ if (!cnode->children)
+ cnode->parent->children = cnode->next;
+}
+
+/***********************************************************************
+ * cnode type para
+ */
+static const struct cnodefuncs para_funcs = {
+ 1, /* indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &para_end, /* end */
+ &para_output,
+};
+
+/***********************************************************************
+ * brief_output : output brief cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+brief_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<brief>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</brief>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type brief
+ */
+static const struct cnodefuncs brief_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &brief_output,
+};
+
+/***********************************************************************
+ * return_output : output return cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+return_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<description><p>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</p></description>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type return
+ */
+static const struct cnodefuncs return_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &return_output,
+};
+
+/***********************************************************************
+ * author_output : output name cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+name_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<name>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</name>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type name
+ */
+static const struct cnodefuncs name_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &name_output,
+};
+
+/***********************************************************************
+ * author_output : output author cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+author_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<author>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</author>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type author
+ */
+static const struct cnodefuncs author_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &author_output,
+};
+
+/***********************************************************************
+ * version_output : output version cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+version_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<version>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</version>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type version
+ */
+static const struct cnodefuncs version_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &version_output,
+};
+
+/***********************************************************************
+ * cnode type code
+ */
+/***********************************************************************
+ * code_end : end a code cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+code_end(struct cnode *cnode)
+{
+ if (incode) {
+ /* The incode flag has not been cleared, so this code cnode is
+ * being ended implicitly. We complain about that. */
+ locerrorexit(cnode->filename, cnode->linenum, "mismatched \\code");
+ }
+}
+
+/***********************************************************************
+ * code_output : output code cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+code_output(struct cnode *cnode, unsigned int indent)
+{
+ /* Note capitalization to differentiate it from HTML code element. */
+ if(cnode->attrtext)
+ printf("%*s<Code %s>", indent, "", cnode->attrtext);
+ else
+ printf("%*s<Code>", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("</Code>\n");
+}
+
+static const struct cnodefuncs code_funcs = {
+ 0, /* indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &code_end, /* end */
+ &code_output,
+};
+
+/***********************************************************************
+ * startpara : start a new para cnode in the parse tree
+ *
+ * Enter: cnode = current cnode
+ * type = vtable for particular type of cnode
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+startpara(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ struct cnode *newcnode;
+ while ((*cnode->funcs->askend)(cnode, type))
+ cnode = endcnode(cnode);
+ newcnode = memalloc(sizeof(struct cnode));
+ newcnode->funcs = type;
+ return startcnode(cnode, newcnode);
+}
+
+/***********************************************************************
+ * cnode type text
+ */
+struct textcnode {
+ struct cnode cn;
+ unsigned char *data;
+ unsigned int len;
+ unsigned int max;
+};
+
+/***********************************************************************
+ * text_end : end a text cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+text_end(struct cnode *cnode)
+{
+ struct textcnode *textcnode = (void *)cnode;
+ textcnode->data[textcnode->len] = 0;
+ textcnode->max = textcnode->len + 1;
+ textcnode->data = memrealloc(textcnode->data, textcnode->max);
+}
+
+/***********************************************************************
+ * text_output : output text cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+text_output(struct cnode *cnode, unsigned int indent)
+{
+ /* We do not indent, in case this is inside a code cnode. */
+ struct textcnode *textcnode = (void *)cnode;
+ unsigned int len = textcnode->len;
+ unsigned const char *p = textcnode->data;
+ while (len) {
+ unsigned int thislen;
+ const char *thisptr;
+ thislen = p[0];
+ /* (void *) cast is to avoid a warning from the MS compiler.
+ * I think the warning is wrong, but I could be wrong. */
+ memcpy((void *)&thisptr, p + 1, sizeof(void *));
+ p += 1 + sizeof(void *);
+ len -= 1 + sizeof(void *);
+ printtext(thisptr, thislen, 0);
+ }
+}
+
+static const struct cnodefuncs text_funcs = {
+ 1, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &text_end, /* end */
+ &text_output,
+};
+
+/***********************************************************************
+ * cnode type html (HTML element)
+ */
+struct htmlcnode {
+ struct cnode cn;
+ const struct htmleldesc *desc;
+ char attrs[1];
+};
+
+/***********************************************************************
+ * html_end : end an html cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+html_end(struct cnode *cnode)
+{
+ if (((struct htmlcnode *)cnode)->desc->flags & HTMLEL_BLOCK)
+ inhtmlblock--;
+}
+
+/***********************************************************************
+ * html_output : output html cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+html_output(struct cnode *cnode, unsigned int indent)
+{
+ struct htmlcnode *htmlcnode = (void *)cnode;
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ printf("%*s", indent, "");
+ if (htmlcnode->cn.children) {
+ printf("<%s%s>", htmlcnode->desc->name, htmlcnode->attrs);
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ putchar('\n');
+ outputchildren(&htmlcnode->cn, indent, 1);
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ printf("%*s", indent, "");
+ printf("</%s>", htmlcnode->desc->name);
+ } else
+ printf("<%s%s/>", htmlcnode->desc->name, htmlcnode->attrs);
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ putchar('\n');
+}
+
+static const struct cnodefuncs html_funcs = {
+ 1, /* indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &html_end, /* end */
+ &html_output,
+};
+
+/***********************************************************************
+ * starthtmlcnode : start a new html cnode
+ *
+ * Enter: cnode = current cnode
+ * htmleldesc = html element descriptor
+ * attrs = attributes text
+ * attrslen = length of attributes text
+ * filename
+ * linenum = line number
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+starthtmlcnode(struct cnode *cnode, const struct htmleldesc *htmleldesc,
+ const char *attrs, unsigned int attrslen,
+ const char *filename, unsigned int linenum)
+{
+ struct htmlcnode *htmlcnode;
+ /* First close enough elements to get to a content
+ * model that will accept this new element. */
+ for (;;) {
+ if (cnode->funcs != &html_funcs) {
+ /* Not in any html element. We can accept any block element
+ * (in which case we need to close the current paragraph
+ * first) or any inline element (in which case we need to
+ * close the current text cnode first). */
+ if (!(htmleldesc->flags & HTMLEL_INLINE)) {
+ if (!(htmleldesc->flags & HTMLEL_BLOCK))
+ locerrorexit(filename, linenum, "<%s> not valid here", htmleldesc->name);
+ while ((*cnode->funcs->askend)(cnode, 0))
+ cnode = endcnode(cnode);
+ } else {
+ while (cnode->funcs == &text_funcs)
+ cnode = endcnode(cnode);
+ }
+ break;
+ }
+ htmlcnode = (struct htmlcnode *)cnode;
+ if (!(htmleldesc->flags & htmlcnode->desc->content))
+ locerrorexit(filename, linenum, "<%s> not valid here", htmleldesc->name);
+ break;
+ }
+ if (htmleldesc->flags & HTMLEL_BLOCK)
+ inhtmlblock++;
+ /* Create the new html cnode. */
+ htmlcnode = memalloc(sizeof(struct htmlcnode) + attrslen);
+ htmlcnode->desc = htmleldesc;
+ htmlcnode->cn.funcs = &html_funcs;
+ htmlcnode->cn.filename = filename;
+ htmlcnode->cn.linenum = linenum;
+ memcpy(htmlcnode->attrs, attrs, attrslen);
+ htmlcnode->attrs[attrslen] = 0;
+ /* Start the html cnode. */
+ cnode = startcnode(cnode, &htmlcnode->cn);
+ return cnode;
+}
+
+/***********************************************************************
+ * param_output : output param cnode
+ *
+ * Enter: cnode for param
+ * indent = indent (nesting) level
+ *
+ * This is only used for a \param inside a \def-device-cap. A normal
+ * \param that gets attached to a function argument gets changed to
+ * a \return so it does not use this output function.
+ */
+static void
+param_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<param identifier=\"%s\">\n", indent, "", paramcnode->name);
+ outputchildren(&paramcnode->cn, indent, 1);
+ printf("%*s</param>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type param
+ */
+static const struct cnodefuncs param_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &param_output,
+};
+
+/***********************************************************************
+ * cnode type throw
+ */
+static const struct cnodefuncs throw_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &return_output,
+};
+
+/***********************************************************************
+ * startparamcnode : start param (or throw) cnode
+ *
+ * Enter: cnode = current cnode
+ * word = name of param
+ * wordlen = length of name
+ * inout = bit 0 = in, bit 1 = out
+ * type = &param_funcs or &throw_funcs
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+startparamcnode(struct cnode *cnode, const char *word, unsigned int wordlen,
+ int inout, const struct cnodefuncs *funcs)
+{
+ struct paramcnode *paramcnode;
+ paramcnode = memalloc(sizeof(struct paramcnode) + wordlen);
+ paramcnode->cn.funcs = funcs;
+ memcpy(paramcnode->name, word, wordlen);
+ paramcnode->name[wordlen] = 0;
+ paramcnode->inout = inout;
+ return startcnode(cnode, &paramcnode->cn);
+}
+
+/***********************************************************************
+ * api_feature_output : output api-feature cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+api_feature_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<api-feature identifier=\"%s\">\n", indent, "", paramcnode->name);
+ outputchildren(cnode, indent, 1);
+ printf("%*s</api-feature>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type api_feature
+ */
+static const struct cnodefuncs api_feature_funcs = {
+ 0, /* !indesc */
+ 0, /* needpara */
+ &default_askend,
+ 0, /* end */
+ &api_feature_output,
+};
+
+/***********************************************************************
+ * device_cap_output : output device-cap cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+device_cap_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<device-cap identifier=\"%s\">\n", indent, "", paramcnode->name);
+ outputchildren(cnode, indent, 1);
+ printf("%*s</device-cap>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type device_cap
+ */
+static const struct cnodefuncs device_cap_funcs = {
+ 0, /* !indesc */
+ 0, /* needpara */
+ &default_askend,
+ 0, /* end */
+ &device_cap_output,
+};
+
+/***********************************************************************
+ * def_api_feature_askend : ask if def-api-feature cnode wants to end at new para
+ *
+ * Enter: cnode for def-api-feature
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-api-feature
+ */
+static int
+def_api_feature_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-api-feature does not end at a plain para, an html block element,
+ * a brief para, or a device-cap. */
+ if (!type || type == &para_funcs || type == &device_cap_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_api_feature_output : output def-api-feature cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_api_feature_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<def-api-feature identifier=\"%s\">\n", indent, "", paramcnode->name);
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-api-feature>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_api_feature
+ */
+static const struct cnodefuncs def_api_feature_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_api_feature_askend,
+ 0, /* end */
+ &def_api_feature_output,
+};
+
+/***********************************************************************
+ * def_api_feature_set_askend : ask if def-api-feature-set cnode wants to end at new para
+ *
+ * Enter: cnode for def-api-feature-set
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-api-feature-set
+ */
+static int
+def_api_feature_set_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-api-feature-set does not end at a plain para, an html block element,
+ * a brief para, or an api-feature. */
+ if (!type || type == &para_funcs || type == &api_feature_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_api_feature_set_output : output def-api-feature-set cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_api_feature_set_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<def-api-feature-set identifier=\"%s\">\n", indent, "", paramcnode->name);
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-api-feature-set>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_api_feature_set
+ */
+static const struct cnodefuncs def_api_feature_set_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_api_feature_set_askend,
+ 0, /* end */
+ &def_api_feature_set_output,
+};
+
+/***********************************************************************
+ * def_instantiated_askend : ask if def-instantiated cnode wants to end at new para
+ *
+ * Enter: cnode for def-instantiated
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-instantiated
+ */
+static int
+def_instantiated_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-instantiated does not end at a plain para, an html block element,
+ * a brief para, or an api-feature. */
+ if (!type || type == &para_funcs || type == &api_feature_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_instantiated_output : output def-instantiated cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_instantiated_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<def-instantiated>\n", indent, "");
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-instantiated>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_instantiated
+ */
+static const struct cnodefuncs def_instantiated_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_instantiated_askend,
+ 0, /* end */
+ &def_instantiated_output,
+};
+
+/***********************************************************************
+ * def_device_cap_askend : ask if def-device-cap cnode wants to end at new para
+ *
+ * Enter: cnode for def-device-cap
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-device-cap
+ */
+static int
+def_device_cap_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-device-cap does not end at a plain para, an html block element,
+ * a \brief para, or a param. */
+ if (!type || type == &para_funcs || type == &param_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_device_cap_output : output def_device-cap cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_device_cap_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<def-device-cap identifier=\"%s\">\n", indent, "", paramcnode->name);
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-device-cap>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_device_cap
+ */
+static const struct cnodefuncs def_device_cap_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_device_cap_askend,
+ 0, /* end */
+ &def_device_cap_output,
+};
+
+/***********************************************************************
+ * addtext : add text to current text node, starting one if necessary
+ *
+ * Enter: cnode = current cnode
+ * text
+ * len = length of text
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+addtext(struct cnode *cnode, const char *text, unsigned int len)
+{
+ struct textcnode *textcnode;
+ if (!len)
+ return cnode;
+ if (cnode->funcs != &text_funcs) {
+ /* Start new text cnode. */
+ textcnode = memalloc(sizeof(struct textcnode));
+ textcnode->cn.funcs = &text_funcs;
+ cnode = startcnode(cnode, &textcnode->cn);
+ }
+ textcnode = (void *)cnode;
+ do {
+ unsigned char buf[1 + sizeof(void *)];
+ unsigned int thislen = len;
+ if (thislen > 255)
+ thislen = 255;
+ /* Encode a record as a single byte length followed by a pointer. */
+ buf[0] = thislen;
+ memcpy(buf + 1, &text, sizeof(void *));
+ /* Add to the text cnode's data. */
+ if (textcnode->len + sizeof(buf) >= textcnode->max) {
+ /* Need to reallocate (or allocate) data buffer. */
+ textcnode->max = textcnode->max ? 2 * textcnode->max : 1024;
+ textcnode->data = memrealloc(textcnode->data, textcnode->max);
+ }
+ memcpy(textcnode->data + textcnode->len, buf, sizeof(buf));
+ textcnode->len += sizeof(buf);
+ text += thislen;
+ len -= thislen;
+ } while (len);
+ return &textcnode->cn;
+}
+
+/***********************************************************************
+ * iswhitespace : determine if character is whitespace
+ *
+ * Enter: ch = character
+ *
+ * Return: 1 if whitespace
+ */
+static inline int
+iswhitespace(int ch)
+{
+ unsigned int i = ch - 1;
+ if (i >= 32)
+ return 0;
+ return 0x80001100 >> i & 1;
+}
+
+/***********************************************************************
+ * parseword : parse the next word, ignoring leading whitespace
+ *
+ * Enter: *pp = text pointer
+ *
+ * Return: 0 else start of word (*pp updated to just beyond end)
+ */
+static const char *
+parseword(const char **pp)
+{
+ const char *p = *pp, *word = 0;
+ int ch = *p;
+ while (iswhitespace(ch))
+ ch = *++p;
+ word = p;
+ while ((unsigned)((ch & ~0x20) - 'A') <= 'Z' - 'A'
+ || (unsigned)(ch - '0') < 10 || ch == '_' || ch == '.'
+ || ch == ':' || ch == '/' || ch == '-')
+ {
+ ch = *++p;
+ }
+ if (p == word)
+ return 0;
+ *pp = p;
+ return word;
+}
+
+/***********************************************************************
+ * Doxygen command handlers
+ *
+ * Enter: p = text just after command
+ * *pcnode = pointer to current cnode struct
+ * type = 0 else cnodefuncs pointer for type of node to start
+ * filename, linenum = current filename and line number (for error reporting)
+ *
+ * Return: p = updated if extra text was eaten
+ *
+ * On return, *pnode is updated if any node was closed or opened.
+ */
+
+/***********************************************************************
+ * Doxygen command handler : \b
+ */
+static const char *
+dox_b(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ const char *word = parseword(&p);
+ /* Silently ignore \b with no following word. */
+ if (word) {
+ struct cnode *mycnode;
+ mycnode = cnode = starthtmlcnode(cnode, HTMLELDESC_B, 0, 0, filename, linenum);
+ cnode = addtext(cnode, word, p - word);
+ while (cnode != mycnode)
+ cnode = endcnode(cnode);
+ cnode = endcnode(cnode);
+ }
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \n
+ */
+static const char *
+dox_n(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ cnode = starthtmlcnode(cnode, HTMLELDESC_BR, 0, 0, filename, linenum);
+ cnode = endcnode(cnode);
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \code
+ */
+static const char *
+dox_code(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ *pcnode = startpara(*pcnode, &code_funcs);
+ (*pcnode)->filename = filename;
+ (*pcnode)->linenum = linenum; /* for reporting mismatched \code error */
+ incode = 1;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \endcode
+ */
+static const char *
+dox_endcode(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ incode = 0;
+ *pcnode = endspecificcnode(*pcnode, &code_funcs, filename, linenum);
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \param
+ */
+static const char *
+dox_param(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ unsigned int inout = 0;
+ const char *word;
+ /* Check for "in", "out" or both as attributes. */
+ if (*p == '[') {
+ for (;;) {
+ p++;
+ if (!memcmp(p, "in", 2)) {
+ inout |= 1;
+ p += 2;
+ } else if (!memcmp(p, "out", 3)) {
+ inout |= 2;
+ p += 3;
+ } else
+ break;
+ if (*p != ',')
+ break;
+ }
+ if (*p != ']')
+ locerrorexit(filename, linenum, "bad attributes on \\param");
+ p++;
+ }
+ /* Get the next word as the parameter name. */
+ word = parseword(&p);
+ if (!word)
+ locerrorexit(filename, linenum, "expected word after \\param");
+ /* Close any open nodes. */
+ while ((*cnode->funcs->askend)(cnode, type))
+ cnode = endcnode(cnode);
+ /* Create a new param cnode. */
+ cnode = startparamcnode(cnode, word, p - word, inout, type);
+ cnode->filename = filename;
+ cnode->linenum = linenum;
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \brief, \return
+ */
+static const char *
+dox_para(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ *pcnode = startpara(*pcnode, type);
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \throw
+ */
+static const char *
+dox_throw(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ const char *word;
+ /* Get the next word as the exception name. */
+ word = parseword(&p);
+ if (!word)
+ locerrorexit(filename, linenum, "expected word after \\throw");
+ /* Close any open nodes. */
+ while ((*cnode->funcs->askend)(cnode, type))
+ cnode = endcnode(cnode);
+ /* Create a new throw cnode. */
+ cnode = startparamcnode(cnode, word, p - word, 0, type);
+ cnode->filename = filename;
+ cnode->linenum = linenum;
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \lang
+ */
+static const char *
+dox_attr(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ const char *word;
+ int len, wordlen, offset = 0;
+ char *attrtext;
+ /* Get the next word as the attribute value. */
+ word = parseword(&p);
+ if (!word)
+ locerrorexit(filename, linenum, "expected word after \\%s", cmdname);
+
+ len = strlen(cmdname) + (wordlen = p-word) + 4; /* p="word"\0 */
+ if(cnode->attrtext)
+ len += (offset = strlen(cnode->attrtext)) + 1; /* add space for space */
+ attrtext = memalloc(len);
+ if(offset) {
+ memcpy(attrtext, cnode->attrtext, offset);
+ attrtext[offset++] = ' ';
+ memfree(((void*)cnode->attrtext));
+ }
+ offset += sprintf(&attrtext[offset], "%s=\"", cmdname);
+ memcpy(&attrtext[offset], word, wordlen);
+ strcpy(&attrtext[offset + wordlen], "\"");
+ cnode->attrtext = attrtext;
+ /* skip delimiter because it won't be done otherwise */
+ if(incode && iswhitespace(*p)) ++p;
+ return p;
+}
+
+/***********************************************************************
+ * commands : table of Doxygen commands
+ */
+struct command {
+ const char *(*func)(const char *p, struct cnode **pcnode, const struct cnodefuncs *type, const char *filename, unsigned int linenum, const char *cmdname);
+ const struct cnodefuncs *type;
+ unsigned int namelen;
+ const char *name;
+};
+static const struct command commands[] = {
+ { &dox_throw, &def_api_feature_funcs, 15, "def-api-feature" },
+ { &dox_throw, &def_api_feature_set_funcs, 19, "def-api-feature-set" },
+ { &dox_para, &def_instantiated_funcs, 16, "def-instantiated" },
+ { &dox_para, &name_funcs, 4, "name" },
+ { &dox_para, &author_funcs, 6, "author" },
+ { &dox_b, 0, 1, "b" },
+ { &dox_para, &brief_funcs, 5, "brief" },
+ { &dox_code, 0, 4, "code" },
+ { &dox_throw, &def_device_cap_funcs, 14, "def-device-cap" },
+ { &dox_attr, 0, 4, "lang" },
+ { &dox_endcode, 0, 7, "endcode" },
+ { &dox_n, 0, 1, "n" },
+ { &dox_param, &param_funcs, 5, "param" },
+ { &dox_para, &return_funcs, 6, "return" },
+ { &dox_throw, &throw_funcs, 5, "throw" },
+ { &dox_throw, &api_feature_funcs, 11, "api-feature" },
+ { &dox_throw, &device_cap_funcs, 10, "device-cap" },
+ { &dox_para, &version_funcs, 7, "version" },
+ { 0, 0, 0 }
+};
+
+/***********************************************************************
+ * parsehtmltag : parse html tag
+ *
+ * Enter: start = start of tag, the '<' char
+ * *pcnode = current cnode
+ * filename = filename
+ * *plinenum = current line number
+ *
+ * Return: just after the tag
+ * *pcnode and *plinenum updated if applicable
+ */
+static const char *
+parsehtmltag(const char *start, struct cnode **pcnode,
+ const char *filename, unsigned int *plinenum)
+{
+ struct cnode *cnode = *pcnode;
+ const char *end = start + 1, *endname = 0, *name = end;
+ int ch = *end;
+ int quote = 0;
+ int close = 0;
+ unsigned int linenum = *plinenum;
+ const struct htmleldesc *htmleldesc;
+ if (ch == '/') {
+ close = 1;
+ ch = *++end;
+ name = end;
+ }
+ /* Find the end of the tag. */
+ for (;;) {
+ if (!ch)
+ locerrorexit(filename, *plinenum, "unterminated HTML tag");
+ if (ch == '\n')
+ linenum++;
+ else if (iswhitespace(ch) || ch == '/') {
+ if (!endname)
+ endname = end;
+ } else if (!quote) {
+ if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '>')
+ break;
+ } else {
+ if (ch == quote)
+ quote = 0;
+ }
+ ch = *++end;
+ }
+ if (!endname)
+ endname = end;
+ end++;
+ /* See if it's an xml open-close tag. */
+ if (!close && endname != name && end[-2] == '/')
+ close = 2;
+ /* Find the tag from our list. */
+ htmleldesc = htmleldescs;
+ for (;;) {
+ if (!htmleldesc->namelen) {
+ locerrorexit(filename, *plinenum, "unrecognized HTML tag %.*s",
+ end - start, start);
+ }
+ if (htmleldesc->namelen == endname - name
+ && !strncasecmp(htmleldesc->name, name, endname - name))
+ {
+ break;
+ }
+ htmleldesc++;
+ }
+ if (close == 1) {
+ /* Closing tag. Find open element to close. */
+ for (;;) {
+ struct htmlcnode *htmlcnode;
+ if (cnode->funcs != &text_funcs) {
+ if (cnode->funcs != &html_funcs) {
+ locerrorexit(filename, *plinenum, "mismatched %.*s",
+ end - start, start);
+ }
+ htmlcnode = (struct htmlcnode *)cnode;
+ if (htmlcnode->desc == htmleldesc)
+ break;
+ if (!(htmlcnode->desc->flags & HTMLEL_AUTOCLOSE)) {
+ locerrorexit(filename, htmlcnode->cn.linenum,
+ "mismatched <%.*s>",
+ htmlcnode->desc->namelen, htmlcnode->desc->name);
+ }
+ }
+ cnode = endcnode(cnode);
+ }
+ cnode = endcnode(cnode);
+ } else {
+ /* Opening tag. */
+ if (close !=2)
+ cnode = starthtmlcnode(cnode, htmleldesc, endname, end - 1 - endname, filename, *plinenum);
+ else // don't include the closing "/" in the attributes list
+ cnode = starthtmlcnode(cnode, htmleldesc, endname, end - 2 - endname, filename, *plinenum);
+ if (close == 2 || (htmleldesc->content & HTMLEL_EMPTY)) {
+ /* Empty element -- close it again. */
+ cnode = endcnode(cnode);
+ }
+ }
+ *pcnode = cnode;
+ *plinenum = linenum;
+ return end;
+}
+
+/***********************************************************************
+ * parsecomment : parse one comment
+ *
+ * Enter: comment struct
+ */
+static void
+parsecomment(struct comment *comment)
+{
+ struct cnode *cnode = &comment->root;
+ const char *p = comment->text + comment->back;
+ unsigned int linenum = comment->linenum - 1;
+ int ch;
+ curcomment = comment;
+ incode = 0;
+ inhtmlblock = 0;
+ cnode->funcs = &root_funcs;
+ for (;;) {
+ /* Start of new line. */
+ const char *starttext;
+ ch = *p;
+ linenum++;
+ {
+ /* Find first non-whitespace character. */
+ const char *p2 = p;
+ int ch2 = ch;
+ while (iswhitespace(ch2))
+ ch2 = *++p2;
+ if (comment->type == TOK_BLOCKCOMMENT && ch2 == '*') {
+ /* Ignore initial * in block comment (even in \code block). */
+ ch2 = *++p2;
+ ch = ch2;
+ p = p2;
+ if (ch == '*')
+ goto checkforlineofstars;
+ while (iswhitespace(ch2))
+ ch2 = *++p2;
+ }
+ if (comment->type == TOK_INLINECOMMENT && ch2 == '/') {
+checkforlineofstars:
+ if (!incode) {
+ /* Ignore whole line of * for block comment or / for inline
+ * comment if that is the only thing on the line. */
+ const char *p3 = p2;
+ int ch3;
+ do ch3 = *++p3; while (ch3 == ch2);
+ while (iswhitespace(ch3)) ch3 = *++p3;
+ if (!ch3 || ch3 == '\n') {
+ /* Reached end of line (or whole comment) -- treat as
+ * empty line. */
+ ch2 = ch3;
+ p2 = p3;
+ }
+ }
+ }
+ if (!incode) {
+ /* Only allow whitespace omission above to take effect if
+ * not in \code block. */
+ ch = ch2;
+ p = p2;
+ }
+ }
+ if (!ch) {
+ /* End of comments -- finish. */
+ break;
+ }
+ if (!incode && !inhtmlblock && ch == '\n') {
+ /* Blank line -- finish any para, but only if not in code and
+ * not in any HTML block element. */
+ while ((*cnode->funcs->askend)(cnode, 0))
+ cnode = endcnode(cnode);
+ p++;
+ continue;
+ }
+ /* Start new para if there isn't already one going. */
+ if (cnode->funcs->needpara)
+ cnode = startpara(cnode, &para_funcs);
+ /* Process text on the line. */
+ starttext = p;
+ while (ch && ch != '\n') {
+ if (ch != '\\' && ch != '<' /* && ch != '@' */ && ch != '$'
+ && ch != '&' && ch != '\r')
+ {
+ ch = *++p;
+ continue;
+ }
+ /* Output any pending text. */
+ if (p - starttext)
+ cnode = addtext(cnode, starttext, p - starttext);
+ /* Ignore \r in DOS line returns */
+ if (ch == '\r') {
+ ch = *++p;
+ starttext = p;
+ continue;
+ }
+ if (ch == '$')
+ locerrorexit(comment->filename, linenum, "use \\$ instead of $");
+ /* See if it is an html named entity. */
+ if (ch == '&' && p[1] != '#') {
+ const char *entity = ENTITIES;
+ /* This search could be faster if the entity names were put
+ * in a hash table or something. */
+ const char *semicolon = strchr(p, ';');
+ unsigned int len;
+ if (!semicolon)
+ locerrorexit(comment->filename, linenum, "unterminated HTML entity");
+ p++;
+ for (;;) {
+ len = strlen(entity);
+ if (!len)
+ locerrorexit(comment->filename, linenum, "unrecognised HTML entity &%.*s;", semicolon - p, p);
+ if (len == semicolon - p && !memcmp(p, entity, len))
+ break;
+ entity += len + 1;
+ entity += strlen(entity) + 1;
+ }
+ entity += len + 1;
+ cnode = addtext(cnode, entity, strlen(entity));
+ p = semicolon + 1;
+ ch = *p;
+ starttext = p;
+ continue;
+ }
+ /* See if it is a backslash escape sequence. */
+ else if (ch == '\\') {
+ const char *match = "\\@&$#<>%";
+ const char *pos;
+ ch = p[1];
+ pos = strchr(match, ch);
+ if (pos) {
+ /* Got a \ escape sequence. */
+ const char *text =
+ "\\\0 @\0 &amp;\0$\0 #\0 &lt;\0 >\0 %"
+ + 6 * (pos - match);
+ cnode = addtext(cnode, text, strlen(text));
+ p += 2;
+ ch = *p;
+ starttext = p;
+ continue;
+ }
+ } else if (ch == '<') {
+ if (incode) {
+ ch = *++p;
+ starttext = p;
+ continue;
+ }
+ /* It's an html tag. */
+ p = parsehtmltag(p, &cnode, comment->filename, &linenum);
+ ch = *p;
+ starttext = p;
+ continue;
+ }
+ {
+ /* Got a doxygen command. First work out its length. */
+ const char *start = ++p;
+ unsigned int cmdlen;
+ const struct command *command;
+ ch = *p;
+ while ((unsigned)((ch & ~0x20) - 'A') <= 'Z' - 'A'
+ || (unsigned)(ch - '0') < 10 || ch == '_' || ch == '-')
+ {
+ ch = *++p;
+ }
+ cmdlen = p - start;
+ if (!cmdlen)
+ locerrorexit(comment->filename, linenum, "\\ or @ without Doxygen command");
+ /* Look it up in the table. */
+ command = commands;
+ for (;;) {
+ if (!command->namelen) {
+ locerrorexit(comment->filename, linenum, "unrecognized Doxygen command '%.*s'",
+ cmdlen + 1, start - 1);
+ }
+ if (command->namelen == cmdlen
+ && !memcmp(command->name, start, cmdlen))
+ {
+ break;
+ }
+ command++;
+ }
+ p = (*command->func)(p, &cnode, command->type,
+ comment->filename, linenum, command->name);
+ ch = *p;
+ starttext = p;
+ }
+ }
+ if (p - starttext) {
+ /* Start new para if there isn't already one going. */
+ if (cnode->funcs->needpara)
+ cnode = startpara(cnode, &para_funcs);
+ cnode = addtext(cnode, starttext, p - starttext);
+ }
+ if (!ch)
+ break;
+ if (cnode->funcs == &text_funcs)
+ addtext(cnode, "\n", 1);
+ p++;
+ }
+ /* Finish the root cnode. */
+ do
+ cnode = endcnode(cnode);
+ while (cnode);
+ assert(!incode);
+ assert(!inhtmlblock);
+}
+
+/***********************************************************************
+ * parsecomments : parse comments
+ *
+ * Enter: comment = first comment in list
+ */
+static void
+parsecomments(struct comment *comment)
+{
+ while (comment) {
+ parsecomment(comment);
+ comment = comment->next;
+ }
+}
+
+/***********************************************************************
+ * attachcommenttonode : attach comment struct to node
+ *
+ * Enter: node = parse node for identifier
+ * comment = comment struct
+ */
+static void
+attachcommenttonode(struct node *node, struct comment *comment)
+{
+ comment->next = node->comments;
+ node->comments = comment;
+}
+
+/***********************************************************************
+ * attachcomments : attach comments to applicable parse nodes
+ *
+ * Enter: comment = first in (reversed) list of comment structs
+ * root = root parse node (for attaching \file comment blocks to)
+ */
+static void
+attachcomments(struct comment *comment, struct node *root)
+{
+ while (comment) {
+ struct comment *next = comment->next;
+ /* See if there are any \param, \return, \throw, \def-api-feature or
+ * \def-device-cap cnodes to detach and attach
+ * elsewhere. (This only looks at top-level nodes, direct children
+ * of the root, so does not detach a \param inside a
+ * \def-device-cap.) */
+ struct cnode **pcnode = &comment->root.children;
+ for (;;) {
+ struct cnode *cnode = *pcnode;
+ if (!cnode)
+ break;
+ if (cnode->funcs == &param_funcs || cnode->funcs == &return_funcs
+ || cnode->funcs == &throw_funcs)
+ {
+ /* Found a \param or \return or \throw to detach. Find the
+ * parameter/exception of the same name, or the return type. */
+ struct node *node;
+ struct comment *newcomment;
+ if (cnode->funcs == &param_funcs) {
+ node = findparamidentifier(comment->node,
+ ((struct paramcnode *)cnode)->name);
+ if (!node)
+ locerrorexit(comment->filename, cnode->linenum, "no parameter '%s' found", ((struct paramcnode *)cnode)->name);
+ } else if (cnode->funcs == &return_funcs) {
+ node = findreturntype(comment->node);
+ if (!node)
+ locerrorexit(comment->filename, cnode->linenum, "no return type found");
+ } else {
+ node = findthrowidentifier(comment->node,
+ ((struct paramcnode *)cnode)->name);
+ if (!node)
+ locerrorexit(comment->filename, cnode->linenum, "no exception '%s' found", ((struct paramcnode *)cnode)->name);
+ }
+ /* Detach the cnode from its old comment. */
+ *pcnode = cnode->next;
+ /* Create a new comment struct to contain this cnode. */
+ newcomment = memalloc(sizeof(struct comment));
+ newcomment->root.funcs = &root_funcs;
+ newcomment->linenum = cnode->linenum;
+ /* Attach the cnode. */
+ newcomment->root.children = cnode;
+ cnode->parent = &newcomment->root;
+ cnode->next = 0;
+ /* Make the cnode a \return one, just so even a \param
+ * uses return_output. */
+ cnode->funcs = &return_funcs;
+ /* Attach the new comment struct to the parse node. */
+ attachcommenttonode(node, newcomment);
+ } else {
+ pcnode = &cnode->next;
+ }
+ }
+ /* Now attach the comment to its identifier parse node. */
+ {
+ struct node *node = comment->node;
+ if (!node)
+ node = root;
+ attachcommenttonode(node, comment);
+ }
+ comment = next;
+ }
+}
+
+/***********************************************************************
+ * processcomments : join, parse and attach comments
+ *
+ * Enter: root = root parse node
+ */
+void
+processcomments(struct node *root)
+{
+ comments = joininlinecomments(comments);
+ parsecomments(comments);
+ attachcomments(comments, root);
+}
+
+/***********************************************************************
+ * outputdescriptive : output descriptive elements for a node
+ *
+ * Enter: node = identifier node that might have some comments
+ * indent = indent (nesting) level
+ */
+void
+outputdescriptive(struct node *node, unsigned int indent)
+{
+ struct comment *comment = node->comments;
+ int indescriptive = 0;
+ while (comment) {
+ struct cnode *root = &comment->root;
+ if (!indescriptive)
+ printf("%*s<descriptive>\n", indent, "");
+ indescriptive = 1;
+ (*root->funcs->output)(root, indent + 2);
+ comment = comment->next;
+ }
+ if (indescriptive)
+ printf("%*s</descriptive>\n", indent, "");
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.h
new file mode 100644
index 000000000..96d18e2cc
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/comment.h
@@ -0,0 +1,25 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef comment_h
+#define comment_h
+
+struct tok;
+struct node;
+
+void addcomment(struct tok *tok);
+void setcommentnode(struct node *node2);
+void processcomments(struct node *root);
+void outputdescriptive(struct node *node, unsigned int indent);
+
+#endif /* ndef comment_h */
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/entities.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/entities.h
new file mode 100644
index 000000000..ff74c1cb3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/entities.h
@@ -0,0 +1,271 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef entities_h
+#define entities_h
+
+#define ENTITIES \
+"nbsp\0&#160;\0" \
+"iexcl\0&#161;\0" \
+"cent\0&#162;\0" \
+"pound\0&#163;\0" \
+"curren\0&#164;\0" \
+"yen\0&#165;\0" \
+"brvbar\0&#166;\0" \
+"sect\0&#167;\0" \
+"uml\0&#168;\0" \
+"copy\0&#169;\0" \
+"ordf\0&#170;\0" \
+"laquo\0&#171;\0" \
+"not\0&#172;\0" \
+"shy\0&#173;\0" \
+"reg\0&#174;\0" \
+"macr\0&#175;\0" \
+"deg\0&#176;\0" \
+"plusmn\0&#177;\0" \
+"sup2\0&#178;\0" \
+"sup3\0&#179;\0" \
+"acute\0&#180;\0" \
+"micro\0&#181;\0" \
+"para\0&#182;\0" \
+"middot\0&#183;\0" \
+"cedil\0&#184;\0" \
+"sup1\0&#185;\0" \
+"ordm\0&#186;\0" \
+"raquo\0&#187;\0" \
+"frac14\0&#188;\0" \
+"frac12\0&#189;\0" \
+"frac34\0&#190;\0" \
+"iquest\0&#191;\0" \
+"Agrave\0&#192;\0" \
+"Aacute\0&#193;\0" \
+"Acirc\0&#194;\0" \
+"Atilde\0&#195;\0" \
+"Auml\0&#196;\0" \
+"Aring\0&#197;\0" \
+"AElig\0&#198;\0" \
+"Ccedil\0&#199;\0" \
+"Egrave\0&#200;\0" \
+"Eacute\0&#201;\0" \
+"Ecirc\0&#202;\0" \
+"Euml\0&#203;\0" \
+"Igrave\0&#204;\0" \
+"Iacute\0&#205;\0" \
+"Icirc\0&#206;\0" \
+"Iuml\0&#207;\0" \
+"ETH\0&#208;\0" \
+"Ntilde\0&#209;\0" \
+"Ograve\0&#210;\0" \
+"Oacute\0&#211;\0" \
+"Ocirc\0&#212;\0" \
+"Otilde\0&#213;\0" \
+"Ouml\0&#214;\0" \
+"times\0&#215;\0" \
+"Oslash\0&#216;\0" \
+"Ugrave\0&#217;\0" \
+"Uacute\0&#218;\0" \
+"Ucirc\0&#219;\0" \
+"Uuml\0&#220;\0" \
+"Yacute\0&#221;\0" \
+"THORN\0&#222;\0" \
+"szlig\0&#223;\0" \
+"agrave\0&#224;\0" \
+"aacute\0&#225;\0" \
+"acirc\0&#226;\0" \
+"atilde\0&#227;\0" \
+"auml\0&#228;\0" \
+"aring\0&#229;\0" \
+"aelig\0&#230;\0" \
+"ccedil\0&#231;\0" \
+"egrave\0&#232;\0" \
+"eacute\0&#233;\0" \
+"ecirc\0&#234;\0" \
+"euml\0&#235;\0" \
+"igrave\0&#236;\0" \
+"iacute\0&#237;\0" \
+"icirc\0&#238;\0" \
+"iuml\0&#239;\0" \
+"eth\0&#240;\0" \
+"ntilde\0&#241;\0" \
+"ograve\0&#242;\0" \
+"oacute\0&#243;\0" \
+"ocirc\0&#244;\0" \
+"otilde\0&#245;\0" \
+"ouml\0&#246;\0" \
+"divide\0&#247;\0" \
+"oslash\0&#248;\0" \
+"ugrave\0&#249;\0" \
+"uacute\0&#250;\0" \
+"ucirc\0&#251;\0" \
+"uuml\0&#252;\0" \
+"yacute\0&#253;\0" \
+"thorn\0&#254;\0" \
+"yuml\0&#255;\0" \
+"fnof\0&#402;\0" \
+"Alpha\0&#913;\0" \
+"Beta\0&#914;\0" \
+"Gamma\0&#915;\0" \
+"Delta\0&#916;\0" \
+"Epsilon\0&#917;\0" \
+"Zeta\0&#918;\0" \
+"Eta\0&#919;\0" \
+"Theta\0&#920;\0" \
+"Iota\0&#921;\0" \
+"Kappa\0&#922;\0" \
+"Lambda\0&#923;\0" \
+"Mu\0&#924;\0" \
+"Nu\0&#925;\0" \
+"Xi\0&#926;\0" \
+"Omicron\0&#927;\0" \
+"Pi\0&#928;\0" \
+"Rho\0&#929;\0" \
+"Sigma\0&#931;\0" \
+"Tau\0&#932;\0" \
+"Upsilon\0&#933;\0" \
+"Phi\0&#934;\0" \
+"Chi\0&#935;\0" \
+"Psi\0&#936;\0" \
+"Omega\0&#937;\0" \
+"alpha\0&#945;\0" \
+"beta\0&#946;\0" \
+"gamma\0&#947;\0" \
+"delta\0&#948;\0" \
+"epsilon\0&#949;\0" \
+"zeta\0&#950;\0" \
+"eta\0&#951;\0" \
+"theta\0&#952;\0" \
+"iota\0&#953;\0" \
+"kappa\0&#954;\0" \
+"lambda\0&#955;\0" \
+"mu\0&#956;\0" \
+"nu\0&#957;\0" \
+"xi\0&#958;\0" \
+"omicron\0&#959;\0" \
+"pi\0&#960;\0" \
+"rho\0&#961;\0" \
+"sigmaf\0&#962;\0" \
+"sigma\0&#963;\0" \
+"tau\0&#964;\0" \
+"upsilon\0&#965;\0" \
+"phi\0&#966;\0" \
+"chi\0&#967;\0" \
+"psi\0&#968;\0" \
+"omega\0&#969;\0" \
+"thetasym\0&#977;\0" \
+"upsih\0&#978;\0" \
+"piv\0&#982;\0" \
+"bull\0&#8226;\0" \
+"hellip\0&#8230;\0" \
+"prime\0&#8242;\0" \
+"Prime\0&#8243;\0" \
+"oline\0&#8254;\0" \
+"frasl\0&#8260;\0" \
+"weierp\0&#8472;\0" \
+"image\0&#8465;\0" \
+"real\0&#8476;\0" \
+"trade\0&#8482;\0" \
+"alefsym\0&#8501;\0" \
+"larr\0&#8592;\0" \
+"uarr\0&#8593;\0" \
+"rarr\0&#8594;\0" \
+"darr\0&#8595;\0" \
+"harr\0&#8596;\0" \
+"crarr\0&#8629;\0" \
+"lArr\0&#8656;\0" \
+"uArr\0&#8657;\0" \
+"rArr\0&#8658;\0" \
+"dArr\0&#8659;\0" \
+"hArr\0&#8660;\0" \
+"forall\0&#8704;\0" \
+"part\0&#8706;\0" \
+"exist\0&#8707;\0" \
+"empty\0&#8709;\0" \
+"nabla\0&#8711;\0" \
+"isin\0&#8712;\0" \
+"notin\0&#8713;\0" \
+"ni\0&#8715;\0" \
+"prod\0&#8719;\0" \
+"sum\0&#8721;\0" \
+"minus\0&#8722;\0" \
+"lowast\0&#8727;\0" \
+"radic\0&#8730;\0" \
+"prop\0&#8733;\0" \
+"infin\0&#8734;\0" \
+"ang\0&#8736;\0" \
+"and\0&#8743;\0" \
+"or\0&#8744;\0" \
+"cap\0&#8745;\0" \
+"cup\0&#8746;\0" \
+"int\0&#8747;\0" \
+"there4\0&#8756;\0" \
+"sim\0&#8764;\0" \
+"cong\0&#8773;\0" \
+"asymp\0&#8776;\0" \
+"ne\0&#8800;\0" \
+"equiv\0&#8801;\0" \
+"le\0&#8804;\0" \
+"ge\0&#8805;\0" \
+"sub\0&#8834;\0" \
+"sup\0&#8835;\0" \
+"nsub\0&#8836;\0" \
+"sube\0&#8838;\0" \
+"supe\0&#8839;\0" \
+"oplus\0&#8853;\0" \
+"otimes\0&#8855;\0" \
+"perp\0&#8869;\0" \
+"sdot\0&#8901;\0" \
+"lceil\0&#8968;\0" \
+"rceil\0&#8969;\0" \
+"lfloor\0&#8970;\0" \
+"rfloor\0&#8971;\0" \
+"lang\0&#9001;\0" \
+"rang\0&#9002;\0" \
+"loz\0&#9674;\0" \
+"spades\0&#9824;\0" \
+"clubs\0&#9827;\0" \
+"hearts\0&#9829;\0" \
+"diams\0&#9830;\0" \
+"quot\0&#34;\0" \
+"amp\0&#38;\0" \
+"lt\0&#60;\0" \
+"gt\0&#62;\0" \
+"OElig\0&#338;\0" \
+"oelig\0&#339;\0" \
+"Scaron\0&#352;\0" \
+"scaron\0&#353;\0" \
+"Yuml\0&#376;\0" \
+"circ\0&#710;\0" \
+"tilde\0&#732;\0" \
+"ensp\0&#8194;\0" \
+"emsp\0&#8195;\0" \
+"thinsp\0&#8201;\0" \
+"zwnj\0&#8204;\0" \
+"zwj\0&#8205;\0" \
+"lrm\0&#8206;\0" \
+"rlm\0&#8207;\0" \
+"ndash\0&#8211;\0" \
+"mdash\0&#8212;\0" \
+"lsquo\0&#8216;\0" \
+"rsquo\0&#8217;\0" \
+"sbquo\0&#8218;\0" \
+"ldquo\0&#8220;\0" \
+"rdquo\0&#8221;\0" \
+"bdquo\0&#8222;\0" \
+"dagger\0&#8224;\0" \
+"Dagger\0&#8225;\0" \
+"permil\0&#8240;\0" \
+"lsaquo\0&#8249;\0" \
+"rsaquo\0&#8250;\0" \
+"euro\0&#8364;\0"
+
+#endif /* ndef entities_h */
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.c b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.c
new file mode 100644
index 000000000..9f9103386
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.c
@@ -0,0 +1,560 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "process.h"
+
+struct file {
+ struct file *next;
+ const char *filename;
+ char *buf;
+ const char *pos, *end;
+ unsigned int linenum;
+};
+
+const char keywords[] = KEYWORDS;
+
+static struct file *file, *firstfile;
+static struct tok tok;
+
+/***********************************************************************
+ * readinput : read all input files into memory
+ *
+ * Enter: argv = 0-terminated array of filenames
+ */
+void
+readinput(const char *const *argv)
+{
+ struct file **pfile = &file;
+ for (;;) {
+ struct file *file;
+ const char *filename = *argv++;
+ char *buf = 0;
+ int len = 0, thislen, isstdin;
+ FILE *handle;
+ if (!filename)
+ break;
+ /* Read the file. */
+ isstdin = !strcmp(filename, "-");
+ if (isstdin) {
+ handle = stdin;
+ filename = "<stdin>";
+ } else {
+ handle = fopen(filename, "rb");
+ if (!handle)
+ errorexit("%s: %s", filename, strerror(errno));
+ }
+ for (;;) {
+ thislen = len ? len * 2 : 4096;
+ buf = memrealloc(buf, len + thislen + 1);
+ thislen = fread(buf + len, 1, thislen, handle);
+ if (!thislen)
+ break;
+ len += thislen;
+ }
+ if (ferror(handle))
+ errorexit("%s: I/O error", filename);
+ if (!isstdin)
+ fclose(handle);
+ buf[len] = 0;
+ buf = memrealloc(buf, len + 1);
+ /* Create the file struct for it. */
+ file = memalloc(sizeof(struct file));
+ *pfile = file;
+ pfile = &file->next;
+ file->filename = filename;
+ file->pos = file->buf = buf;
+ file->end = buf + len;
+ file->linenum = 1;
+ }
+ *pfile = 0;
+ firstfile = file;
+}
+
+/***********************************************************************
+ * lexerrorexit : error and exit with line number
+ */
+static void
+lexerrorexit(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlocerrorexit(file->filename, file->linenum, format, ap);
+ va_end(ap);
+}
+
+/***********************************************************************
+ * lexblockcomment : lex a block comment
+ *
+ * Enter: start = start of comment
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexblockcomment(const char *start)
+{
+ const char *p = start + 1;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ for (;;) {
+ int ch = *++p;
+ if (!ch)
+ lexerrorexit("unterminated block comment");
+ if (ch != '*') {
+ if (ch == '\n')
+ file->linenum++;
+ continue;
+ }
+ ch = p[1];
+ if (!ch)
+ lexerrorexit("unterminated block comment");
+ if (ch == '/')
+ break;
+ }
+ p += 2;
+ file->pos = p;
+ tok.type = TOK_BLOCKCOMMENT;
+ tok.start = start + 2;
+ tok.len = p - start - 4;
+ return &tok;
+}
+
+/***********************************************************************
+ * lexinlinecomment : lex an inline comment
+ *
+ * Enter: start = start of comment, starts with "//"
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexinlinecomment(const char *start)
+{
+ const char *p = start + 2;
+ p = start + 1;
+ for (;;) {
+ int ch = *++p;
+ if (!ch || ch == '\n')
+ break;
+ }
+ p++;
+ file->pos = p;
+ tok.type = TOK_INLINECOMMENT;
+ tok.start = start + 2;
+ tok.len = p - start - 2;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum++;
+ return &tok;
+}
+
+/***********************************************************************
+ * lexnumber : lex a number (or just a '-' symbol)
+ *
+ * Enter: start = start of token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ *
+ * The IDL grammar seems to say that a float can't start with a
+ * decimal point, so that's what we have implemented here.
+ */
+static struct tok *
+lexnumber(const char *start)
+{
+ for (;;) {
+ const char *p = start;
+ const char *octalend = start;
+ int ch = *p;
+ enum { STATE_START, STATE_INT, STATE_HEX, STATE_OCTAL, STATE_BADOCTAL,
+ STATE_DP, STATE_EXPSTART, STATE_EXPSIGN, STATE_EXP
+ } state = STATE_START;
+ if (ch == '-') {
+ ch = *++p;
+ if (ch == 'I') { // starts of Infinity
+ char * infinity = "-Infinity";
+ unsigned int len = strlen(infinity);
+ if (!memcmp(start, infinity, len)) {
+ tok.type = TOK_minusinfinity;
+ tok.start = start;
+ tok.len = len;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = start + len;
+ return &tok;
+ }
+ }
+ }
+ if (ch == '0') {
+ state = STATE_OCTAL;
+ ch = *++p;
+ if ((ch & ~0x20) == 'X') {
+ state = STATE_HEX;
+ ch = *++p;
+ }
+ }
+
+ for (;;) {
+ if ((unsigned)(ch - '0') >= 8) {
+ if ((ch & -2) == '8') {
+ if (state == STATE_OCTAL) {
+ state = STATE_BADOCTAL;
+ octalend = p;
+ }
+ } else if ((unsigned)((ch & ~0x20) - 'A') <= 'F' - 'A') {
+ if (state != STATE_HEX) {
+ if ((ch & ~0x20) != 'E')
+ break;
+ if (state == STATE_HEX || state >= STATE_EXPSTART || state == STATE_START)
+ break;
+ state = STATE_EXPSTART;
+ }
+ } else if (ch == '.') {
+ if (state == STATE_HEX || state >= STATE_DP)
+ break;
+ state = STATE_DP;
+ } else if (ch == '-') {
+ if (state != STATE_EXPSTART)
+ break;
+ state = STATE_EXPSIGN;
+ } else
+ break;
+ }
+ ch = *++p;
+ if (state == STATE_START)
+ state = STATE_INT;
+ else if (state == STATE_EXPSTART || state == STATE_EXPSIGN)
+ state = STATE_EXP;
+ }
+ switch (state) {
+ case STATE_START:
+ /* Must have just been a - character by itself. */
+ tok.type = '-';
+ p = start + 1;
+ break;
+ case STATE_BADOCTAL:
+ p = octalend;
+ /* fall through... */
+ case STATE_INT:
+ case STATE_OCTAL:
+ tok.type = TOK_INTEGER;
+ break;
+ case STATE_HEX:
+ if (p - start == 2 || (p - start == 3 && *start == '-'))
+ p = start + 1;
+ tok.type = TOK_INTEGER;
+ break;
+ case STATE_EXP:
+ case STATE_DP:
+ tok.type = TOK_FLOAT;
+ break;
+ case STATE_EXPSIGN:
+ p--;
+ /* fall through... */
+ case STATE_EXPSTART:
+ p--;
+ tok.type = TOK_FLOAT;
+ break;
+ }
+ tok.start = start;
+ tok.len = p - start;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = p;
+ return &tok;
+ }
+}
+
+/***********************************************************************
+ * lexstring : lex a quoted string
+ *
+ * Enter: start = start of token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexstring(const char *start)
+{
+ for (;;) {
+ const char *p = start + 1;
+ int ch = *p;
+ for (;;) {
+ if (!ch || ch == '\n')
+ lexerrorexit("unterminated string");
+ if (ch == '"') {
+ tok.type = TOK_STRING;
+ tok.start = start + 1;
+ tok.len = p - start - 1;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = p + 1;
+ return &tok;
+ }
+ /* Note the IDL spec doesn't seem to allow for escape sequences
+ * in strings. */
+ ch = *++p;
+ }
+ }
+}
+
+/***********************************************************************
+ * lexidentifier : lex an identifier
+ *
+ * Enter: start = start of token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexidentifier(const char *start)
+{
+ const char *p = start + 1;
+ for (;;) {
+ int ch = *p;
+ if (ch != '_' && (unsigned)(ch - '0') >= 10
+ && (unsigned)((ch & ~0x20) - 'A') > 'Z' - 'A')
+ {
+ break;
+ }
+ p++;
+ }
+ tok.type = TOK_IDENTIFIER;
+ tok.start = start;
+ tok.len = p - start;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = p;
+ /* See if this is a keyword. (This search is a bit n-squared.) */
+ {
+ unsigned int type = TOK_DOMString;
+ p = keywords;
+ for (;;) {
+ unsigned int len = strlen(p);
+ if (!len)
+ break;
+ if (len == tok.len && !memcmp(start, p, len)) {
+ tok.type = type;
+ break;
+ }
+ p += len + 1;
+ type++;
+ }
+ }
+ return &tok;
+}
+
+/***********************************************************************
+ * lex : retrieve next token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+struct tok *
+lex(void)
+{
+ const char *p;
+ int ch;
+ for (;;) {
+ if (!file) {
+ tok.type = TOK_EOF;
+ tok.start = "end of file";
+ tok.len = strlen(tok.start);
+ return &tok;
+ }
+ tok.prestart = p = file->pos;
+ /* Flush whitespace. */
+ for (;;) {
+ ch = *p++;
+ switch (ch) {
+ case ' ':
+ case '\t':
+ case '\r':
+ continue;
+ case '\n':
+ ++file->linenum;
+ tok.prestart = p;
+ continue;
+ }
+ break;
+ }
+ p--;
+ if (ch)
+ break;
+ if (p != file->end)
+ lexerrorexit("\\0 byte not allowed");
+ file = file->next;
+ }
+ /* See if we have a comment. */
+ tok.start = p;
+ if (ch == '/') {
+ switch (*++p) {
+ case '*':
+ return lexblockcomment(p - 1);
+ case '/':
+ return lexinlinecomment(p - 1);
+ }
+ tok.type = '/';
+ } else {
+ /* Handle things that start with '-', which is either '-' as a token,
+ * or a number. Handle numbers. */
+ if (ch == '-' || (unsigned)(ch - '0') < 10)
+ return lexnumber(p);
+ /* Handle string. */
+ if (ch == '"')
+ return lexstring(p);
+ /* Handle identifier. */
+ if (ch == '_' || (unsigned)((ch & ~0x20) - 'A') <= 'Z' - 'A')
+ return lexidentifier(p);
+ /* The only multi-symbol token are ... and [] */
+ if (ch == '.') {
+ tok.type = '.';
+ if (*++p == '.' && p[1] == '.') {
+ tok.type = TOK_ELLIPSIS;
+ p += 2;
+ }
+ goto done;
+ }
+ if (ch == '[') {
+ tok.type = '[';
+ if (*++p == ']') {
+ tok.type = TOK_DOUBLEBRACKET;
+ p++;
+ }
+ goto done;
+ }
+ }
+ /* Single symbol token. */
+ tok.type = ch;
+ p++;
+done:
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ tok.len = p - tok.start;
+ file->pos = p;
+ return &tok;
+}
+
+/***********************************************************************
+ * outputwidl : output literal Web IDL input that node was parsed from
+ *
+ * Enter: node = parse node to output literal Web IDL for
+ */
+void
+outputwidl(struct node *node)
+{
+ const char *start = node->wsstart, *end = node->end;
+ /* Find the file that start is in. */
+ struct file *file = firstfile;
+ while (start < file->buf || start >= file->end) {
+ file = file->next;
+ assert(file);
+ }
+ /* Find the (current or) next node that has node->start set. Any such
+ * node needs to be put inside a <ref> element. */
+ while (node && !node->start)
+ node = nodewalk(node);
+ /* Output until we get to the end. This has to cope with the text
+ * spanning multiple input files. */
+ for (;;) {
+ int final = end >= file->buf && end <= file->end;
+ const char *thisend = final ? end : file->end;
+ /* Output the Web IDL, omitting comments. */
+ while (start != end) {
+ const char *p, *p2, *comment, *endcomment;
+ int ch;
+ if (node && start == node->start) {
+ /* We are on the start of the present node in the tree
+ * walk. Put it in a <ref>. */
+ fputs("<ref>", stdout);
+ printtext(node->start, node->end - node->start, 1);
+ fputs("</ref>", stdout);
+ start = node->end;
+ /* Skip to the next node with node->start set if any. */
+ do
+ node = nodewalk(node);
+ while (node && !node->start);
+ continue;
+ }
+ p2 = thisend;
+ if (node && node->start >= file->buf && node->start < p2)
+ p2 = node->start;
+ p = memchr(start, '/', p2 - start);
+ if (!p) {
+ printtext(start, p2 - start, 1);
+ if (p2 != thisend) {
+ start = p2;
+ continue;
+ }
+ break;
+ }
+ /* See if we're at the start of a comment. If so find the end. */
+ comment = 0;
+ if (p + 1 != thisend) {
+ switch (p[1]) {
+ case '*':
+ /* Block comment. */
+ comment = p;
+ p++;
+ do
+ p = memchr(p + 1, '*', thisend - p - 1);
+ while (p[1] != '/');
+ endcomment = p + 2;
+ break;
+ case '/':
+ /* Inline comment. */
+ comment = p;
+ p = memchr(p, '\n', thisend - p);
+ if (!p)
+ p = thisend;
+ endcomment = p;
+ break;
+ }
+ }
+ if (!comment) {
+ /* Not at start of comment. */
+ p++;
+ printtext(start, p - start, 1);
+ start = p;
+ assert(start <= end);
+ continue;
+ }
+ /* If the comment has only whitespace before it on the line,
+ * eat that up. */
+ p = comment;
+ while (p != start && ((ch = p[-1]) == ' ' || ch == '\t'))
+ p--;
+ if (p == start || p[-1] == '\n') {
+ comment = p;
+ /* If the comment has only whitespace after it to the end
+ * of the line, eat that and the newline up. This always
+ * happens for an inline comment on a line by itself. */
+ p = endcomment;
+ while (p != thisend && ((ch = *p) == ' ' || ch == '\t'))
+ p++;
+ if (p != thisend && *p == '\n')
+ p++;
+ endcomment = p;
+ }
+ printtext(start, comment - start, 1);
+ start = endcomment;
+ if (start > thisend)
+ start = thisend;
+ }
+ if (final)
+ break;
+ file = file->next;
+ assert(file);
+ start = file->buf;
+ }
+}
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.h
new file mode 100644
index 000000000..e30b77b36
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/lex.h
@@ -0,0 +1,141 @@
+
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef lex_h
+#define lex_h
+
+// starting from "attribute" are the list of names allowed as arguments identifier
+#define KEYWORDS \
+ "DOMString\0" \
+ "ByteString\0" \
+ "Date\0" \
+ "RegExp\0" \
+ "false\0" \
+ "object\0" \
+ "true\0" \
+ "any\0" \
+ "boolean\0" \
+ "byte\0" \
+ "double\0" \
+ "float\0" \
+ "Infinity\0" \
+ "-Infinity\0" \
+ "iterator\0" \
+ "long\0" \
+ "NaN\0" \
+ "null\0" \
+ "octet\0" \
+ "optional\0" \
+ "or\0" \
+ "readonly\0" \
+ "sequence\0" \
+ "short\0" \
+ "unsigned\0" \
+ "void\0" \
+ "attribute\0" \
+ "callback\0" \
+ "const\0" \
+ "creator\0" \
+ "deleter\0" \
+ "dictionary\0" \
+ "enum\0" \
+ "exception\0" \
+ "getter\0" \
+ "implements\0" \
+ "inherit\0" \
+ "interface\0" \
+ "legacycaller\0" \
+ "partial\0" \
+ "serializer\0" \
+ "setter\0" \
+ "static\0" \
+ "stringifier\0" \
+ "typedef\0" \
+ "unrestricted\0"
+
+
+enum toktype {
+ TOK_EOF = -1,
+ TOK_BLOCKCOMMENT = 0x80,
+ TOK_INLINECOMMENT, TOK_INTEGER, TOK_FLOAT, TOK_IDENTIFIER,
+ TOK_STRING, TOK_ELLIPSIS, TOK_DOUBLEBRACKET,
+ /* Keywords must be in the same order as above. */
+ TOK_DOMString,
+ TOK_ByteString,
+ TOK_Date,
+ TOK_RegExp,
+ TOK_false,
+ TOK_object,
+ TOK_true,
+ TOK_any,
+ TOK_boolean,
+ TOK_byte,
+ TOK_double,
+ TOK_float,
+ TOK_infinity,
+ TOK_minusinfinity,
+ TOK_iterator,
+ TOK_long,
+ TOK_NaN,
+ TOK_null,
+ TOK_octet,
+ TOK_optional,
+ TOK_or,
+ TOK_readonly,
+ TOK_sequence,
+ TOK_short,
+ TOK_unsigned,
+ TOK_void,
+ /* Below that line are keywords that are allowed as arguments names */
+ TOK_attribute,
+ TOK_callback,
+ TOK_const,
+ TOK_creator,
+ TOK_deleter,
+ TOK_dictionary,
+ TOK_enum,
+ TOK_exception,
+ TOK_getter,
+ TOK_implements,
+ TOK_inherit,
+ TOK_interface,
+ TOK_legacycaller,
+ TOK_partial,
+ TOK_serializer,
+ TOK_setter,
+ TOK_static,
+ TOK_stringifier,
+ TOK_typedef,
+ TOK_unrestricted,
+};
+
+struct tok {
+ enum toktype type;
+ const char *filename;
+ unsigned int linenum;
+ const char *prestart;
+ const char *start;
+ unsigned int len;
+};
+
+extern const char *filename;
+extern const char keywords[];
+
+struct node;
+
+void readinput(const char *const *argv);
+struct tok *lex(void);
+void outputwidl(struct node *node);
+
+#endif /* ndef lex_h */
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/main.c b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/main.c
new file mode 100644
index 000000000..df90e347d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/main.c
@@ -0,0 +1,63 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <string.h>
+#include "misc.h"
+#include "process.h"
+
+static const char nodtdopt[] = "-no-dtd-ref";
+const char *progname;
+
+/***********************************************************************
+ * options : process command line options
+ *
+ * Enter: argv
+ *
+ * Return: argv stepped to point to first non-option argument
+ */
+static const char *const *
+options(int argc, const char *const *argv)
+{
+ /* Set progname for error messages etc. */
+ {
+ const char *base;
+ progname = argv[0];
+ base = strrchr(progname, '/');
+#ifdef DIRSEP
+ {
+ const char *base2 = strrchr(base, '\\');
+ if (base2 > base)
+ base = base2;
+ }
+#endif /* def DIRSEP */
+ if (base)
+ progname = base + 1;
+ }
+ return (argc > 1 && strncmp(argv[1], nodtdopt, sizeof nodtdopt) == 0)
+ ? argv + 2 : argv + 1;
+}
+
+/***********************************************************************
+ * main : main code for bondiidl command
+ */
+int
+main(int argc, char **argv)
+{
+ const char *const *parg;
+ parg = options(argc, (const char *const *)argv);
+ if (!*parg)
+ errorexit("usage: %s [-no-dtd-ref] <interface>.widl ...", progname);
+ processfiles(parg, parg == (const char *const *)argv + 1);
+ return 0;
+}
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.c b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.c
new file mode 100644
index 000000000..37aff3f34
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.c
@@ -0,0 +1,119 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc.h"
+#include "os.h" /* to get va_copy on windows */
+
+extern const char *progname;
+
+/***********************************************************************
+ * memory allocation wrappers
+ */
+void *
+memalloc(size_t size)
+{
+ void *ptr = malloc(size);
+ if (!ptr)
+ errorexit("out of memory");
+ /* Zero initialise memory from memalloc. */
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+void *
+memrealloc(void *ptr, size_t size)
+{
+ void *newptr = realloc(ptr, size);
+ if (!newptr)
+ errorexit("out of memory");
+ return newptr;
+}
+
+void
+memfree(void *ptr)
+{
+ *(int *)ptr = 0xfefefefe;
+ free(ptr);
+}
+
+/***********************************************************************
+ * vmemprintf, memprintf : allocate buffer and sprintf into it
+ */
+char *
+memprintf(const char *format, ...)
+{
+ va_list ap;
+ char *buf;
+ va_start(ap, format);
+ buf = vmemprintf(format, ap);
+ va_end(ap);
+ return buf;
+}
+
+char *
+vmemprintf(const char *format, va_list ap)
+{
+ char *buf;
+ unsigned int max, len;
+ va_list ap2;
+ max = 16;
+ for (;;) {
+ va_copy(ap2, ap);
+ buf = memalloc(max);
+ len = vsnprintf(buf, max, format, ap2);
+ va_end(ap2);
+ if (len < max)
+ break;
+ memfree(buf);
+ max *= 2;
+ }
+ return buf;
+}
+
+/***********************************************************************
+ * errorexit : print error message then exit
+ */
+void
+vlocerrorexit(const char *filename, unsigned int linenum,
+ const char *format, va_list ap)
+{
+ if (filename)
+ fprintf(stderr, linenum ? "%s: %i: " : "%s: ", filename, linenum);
+ vfprintf(stderr, format, ap);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+void
+locerrorexit(const char *filename, unsigned int linenum,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlocerrorexit(filename, linenum, format, ap);
+ va_end(ap);
+}
+
+void
+errorexit(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlocerrorexit(0, 0, format, ap);
+ va_end(ap);
+}
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.h
new file mode 100644
index 000000000..01c36d218
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/misc.h
@@ -0,0 +1,31 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef misc_h
+#define misc_h
+#include <stdarg.h>
+#include <stdlib.h>
+
+void *memalloc(size_t size);
+void *memrealloc(void *ptr, size_t size);
+void memfree(void *ptr);
+
+char *vmemprintf(const char *format, va_list ap);
+char *memprintf(const char *format, ...);
+
+void vlocerrorexit(const char *filename, unsigned int linenum, const char *format, va_list ap);
+void locerrorexit(const char *filename, unsigned int linenum, const char *format, ...);
+void errorexit(const char *format, ...);
+
+#endif /* ndef misc_h */
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.c b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.c
new file mode 100644
index 000000000..d8f737909
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.c
@@ -0,0 +1,331 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Node-specific functions
+ ***********************************************************************/
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "comment.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "process.h"
+
+struct node *
+newelement(const char *name)
+{
+ struct element *element = memalloc(sizeof(struct element));
+ element->n.type = NODE_ELEMENT;
+ element->name = name;
+ return &element->n;
+}
+
+struct node *
+newattr(const char *name, const char *val)
+{
+ struct attr *attr = memalloc(sizeof(struct attr));
+ attr->n.type = NODE_ATTR;
+ attr->name = name;
+ attr->value = val;
+ return &attr->n;
+}
+
+struct node *
+newattrlist(void)
+{
+ struct attrlist *attrlist = memalloc(sizeof(struct attrlist));
+ attrlist->n.type = NODE_ATTRLIST;
+ return &attrlist->n;
+}
+
+/***********************************************************************
+ * addnode : add node as child of another node
+ *
+ * Enter: parent node
+ * child node
+ *
+ * The children list is constructed backwards. This is fixed later with
+ * a call to reversechildren.
+ *
+ * If child is an attrlist, its children are added to parent and the
+ * attrlist is freed.
+ */
+void
+addnode(struct node *parent, struct node *child)
+{
+ if (!child)
+ return;
+ if (child->type == NODE_ATTRLIST) {
+ /* Add the attrs in the attrlist to parent. */
+ struct node *child2;
+ reversechildren(child);
+ child2 = child->children;
+ memfree(child);
+ while (child2) {
+ struct node *next = child2->next;
+ addnode(parent, child2);
+ child2 = next;
+ }
+ } else {
+ child->next = parent->children;
+ parent->children = child;
+ child->parent = parent;
+ }
+}
+
+/***********************************************************************
+ * reversechildren : recursively reverse child lists
+ *
+ * Also sets parent field on each node.
+ */
+void
+reversechildren(struct node *node)
+{
+ struct node *newlist = 0;
+ struct node *child = node->children;
+ while (child) {
+ struct node *next = child->next;
+ child->parent = node;
+ child->next = newlist;
+ newlist = child;
+ reversechildren(child);
+ child = next;
+ }
+ node->children = newlist;
+}
+
+/***********************************************************************
+ * nodeisempty : test if node is empty (has no children)
+ */
+int
+nodeisempty(struct node *node)
+{
+ return !node->children;
+}
+
+/***********************************************************************
+ * nodewalk : single step of depth last traversal of node tree
+ *
+ * Return: next node in walk, 0 if finished
+ */
+struct node *
+nodewalk(struct node *node)
+{
+ if (node->children)
+ return node->children;
+ if (node->next)
+ return node->next;
+ do {
+ node = node->parent;
+ if (!node)
+ return 0;
+ } while (!node->next);
+ return node->next;
+}
+
+/***********************************************************************
+ * findchildelement : find child element of a particular name
+ *
+ * Enter: node = element
+ * name = name to find
+ *
+ * Return: 0 else child element of that name
+ */
+static struct node *
+findchildelement(struct node *node, const char *name)
+{
+ node = node->children;
+ while (node) {
+ if (node->type == NODE_ELEMENT) {
+ struct element *element = (void *)node;
+ if (!strcmp(element->name, name))
+ break;
+ }
+ node = node->next;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * getattr : get value of attribute
+ *
+ * Enter: node = element to find attribute in
+ * name = name of attribute
+ *
+ * Return: 0 if not found, else 0-terminated string value
+ */
+const char *
+getattr(struct node *node, const char *name)
+{
+ node = node->children;
+ while (node) {
+ if (node->type == NODE_ATTR) {
+ struct attr *attr = (void *)node;
+ if (!strcmp(attr->name, name))
+ return attr->value;
+ }
+ node = node->next;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * findchildelementwithnameattr : find child element with a name attribute
+ * of a particular value
+ *
+ * Enter: node = element
+ * name = name to find
+ *
+ * Return: 0 else child element with name attr of that value
+ */
+static struct node *
+findchildelementwithnameattr(struct node *node, const char *name)
+{
+ node = node->children;
+ while (node) {
+ if (node->type == NODE_ELEMENT) {
+ const char *s = getattr(node, "name");
+ if (s && !strcmp(s, name))
+ break;
+ }
+ node = node->next;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * findreturntype : find Type parse node for return type
+ *
+ * Enter: node = Operation element
+ *
+ * Return: 0 if not found, else Type parse node for return type
+ */
+struct node *
+findreturntype(struct node *node)
+{
+ return findchildelement(node, "Type");
+}
+
+/***********************************************************************
+ * findparamidentifier : find identifier parse node for parameter
+ *
+ * Enter: node = Operation element
+ * name = parameter name to find
+ *
+ * Return: 0 if not found, else node struct for parameter identifier
+ */
+struct node *
+findparamidentifier(struct node *node, const char *name)
+{
+ node = findchildelement(node, "ArgumentList");
+ if (node)
+ node = findchildelementwithnameattr(node, name);
+ return node;
+}
+
+/***********************************************************************
+ * findthrowidentifier : find identifier parse node for exception name
+ *
+ * Enter: node = Operation element
+ * name = exception name to find
+ *
+ * Return: 0 if not found, else node for Name element, child of Raises
+ * or SetRaises
+ */
+struct node *
+findthrowidentifier(struct node *node, const char *name)
+{
+ struct node *node2 = findchildelement(node, "Raises");
+ if (node2)
+ node2 = findchildelementwithnameattr(node2, name);
+ if (!node2) {
+ node2 = findchildelement(node, "SetRaises");
+ if (node2)
+ node2 = findchildelementwithnameattr(node2, name);
+ }
+ return node2;
+}
+
+/***********************************************************************
+ * outputid : output the id of a node
+ */
+static void
+outputid(struct node *node)
+{
+ if (node->parent)
+ outputid(node->parent);
+ if (node->id) {
+ fputs("::", stdout);
+ printtext(node->id, strlen(node->id), 1);
+ }
+}
+
+/***********************************************************************
+ * outputnode : output node and its children
+ *
+ * Enter: node = node to output, assumed to be an element
+ * indent
+ */
+void
+outputnode(struct node *node, unsigned int indent)
+{
+ struct element *element = (void *)node;
+ struct node *child;
+ int empty = 1;
+ printf("%*s<%s", indent, "", element->name);
+ child = element->n.children;
+ while (child) {
+ switch(child->type) {
+ case NODE_ELEMENT:
+ empty = 0;
+ break;
+ case NODE_ATTR:
+ {
+ struct attr *attr = (void *)child;
+ printf(" %s=\"", attr->name);
+ printtext(attr->value, strlen(attr->value), 1);
+ printf("\"");
+ }
+ break;
+ }
+ child = child->next;
+ }
+ if (node->id) {
+ printf(" id=\"");
+ outputid(node);
+ printf("\"");
+ }
+ if (!empty || node->comments || node->wsstart) {
+ printf(">\n");
+ if (node->wsstart) {
+ printf("%*s <webidl>", indent, "");
+ outputwidl(node);
+ printf("</webidl>\n");
+ }
+ outputdescriptive(node, indent + 2);
+ child = element->n.children;
+ while (child) {
+ switch(child->type) {
+ case NODE_ELEMENT:
+ outputnode(child, indent + 2);
+ break;
+ }
+ child = child->next;
+ }
+ printf("%*s</%s>\n", indent, "", element->name);
+ } else
+ printf("/>\n");
+}
+
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.h
new file mode 100644
index 000000000..2d6e38e53
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/node.h
@@ -0,0 +1,65 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef node_h
+#define node_h
+
+/* struct node : a node in the parse tree (excluding comments) */
+enum { NODE_ELEMENT, NODE_ATTR, NODE_ATTRLIST };
+struct node {
+ int type;
+ struct node *next;
+ struct node *parent;
+ struct node *children;
+ struct comment *comments; /* list of comments attached to this node */
+ /* If wsstart and end are set, they give the literal Web IDL that can
+ * be output in a <webidl> element. */
+ const char *wsstart;
+ /* If start and end are set, they give the text of a scoped name that
+ * can be enclosed in a <ref> when outputting a <webidl> element for
+ * an ancestor element. */
+ const char *start;
+ const char *end;
+ const char *id;
+};
+
+struct element {
+ struct node n;
+ const char *name;
+};
+
+struct attr {
+ struct node n;
+ const char *name;
+ const char *value;
+};
+
+struct attrlist {
+ struct node n;
+};
+
+struct node *newelement(const char *name);
+struct node *newattr(const char *name, const char *val);
+struct node *newattrlist(void);
+void addnode(struct node *parent, struct node *child);
+void reversechildren(struct node *node);
+int nodeisempty(struct node *node);
+const char *getattr(struct node *node, const char *name);
+struct node *nodewalk(struct node *node);
+struct node *findreturntype(struct node *node);
+struct node *findparamidentifier(struct node *node, const char *name);
+struct node *findthrowidentifier(struct node *node, const char *name);
+void outputnode(struct node *node, unsigned int indent);
+
+#endif /* ndef node_h */
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/os.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/os.h
new file mode 100644
index 000000000..ac8f4189d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/os.h
@@ -0,0 +1,31 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef os_h
+#define os_h
+
+/* Linux configuration */
+#if defined(__gnu_linux__)
+
+
+/* Windows configuration */
+#elif defined(_MSC_VER)
+
+#define inline __inline
+#define strncasecmp strnicmp
+#define snprintf _snprintf
+#define va_copy(a,b) ((a)=(b))
+
+#endif
+
+#endif /* ndef os_h */
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.c b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.c
new file mode 100644
index 000000000..c0e8454ce
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.c
@@ -0,0 +1,1414 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Hand-crafted recursive descent parser for Web IDL grammar.
+ ***********************************************************************/
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "comment.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "parse.h"
+
+/***********************************************************************
+ * tokerrorexit : error and exit with line number from token
+ */
+static void
+tokerrorexit(struct tok *tok, const char *format, ...)
+{
+ va_list ap;
+ char *m;
+ va_start(ap, format);
+ m = vmemprintf(format, ap);
+ if (tok->type == TOK_EOF)
+ locerrorexit(tok->filename, tok->linenum, "at end of input: %s", m);
+ else
+ locerrorexit(tok->filename, tok->linenum, "at '%.*s': %s", tok->len, tok->start, m);
+ va_end(ap);
+}
+
+/***********************************************************************
+ * lexnocomment : lex next token, discarding or storing comments
+ *
+ * A block comment starting with |** or |*! is a doxygen comment.
+ * If it starts with |**< or |*!< then it refers to the previous
+ * identifier, not the next one. (I am using | to represent / otherwise
+ * this comment would be illegal.)
+ *
+ * An inline comment starting with /// or //! is a doxygen comment.
+ * If it starts with ///< or //!< then it refers to the previous
+ * identifier, not the next one.
+ */
+static struct tok *
+lexnocomment(void)
+{
+ struct tok *tok;
+ for (;;) {
+ tok = lex();
+ if (tok->type != TOK_BLOCKCOMMENT && tok->type != TOK_INLINECOMMENT)
+ break;
+ addcomment(tok);
+ }
+ return tok;
+}
+
+/***********************************************************************
+ * eat : check token then read the following one
+ *
+ * Enter: tok struct
+ * type = type of token expected, error given if no match
+ *
+ * On return, tok is updated to the following token.
+ */
+static void
+eat(struct tok *tok, int type)
+{
+ if (tok->type != type) {
+ const char *p;
+ if (type < TOK_DOMString)
+ tokerrorexit(tok, "expected '%c'", type);
+ p = keywords;
+ while (type != TOK_DOMString) {
+ p += strlen(p) + 1;
+ type--;
+ }
+ tokerrorexit(tok, "expected '%s'", p);
+ }
+ lexnocomment();
+}
+
+/***********************************************************************
+ * setid : flag that an id attribute is required on node
+ *
+ * Enter: node
+ *
+ * node->id is set to the value of the name attribute. This makes
+ * outputnode give it an id attribute whose value is the id attribute
+ * of the parent if any, then "::", then node->id.
+ */
+static void
+setid(struct node *node)
+{
+ node->id = getattr(node, "name");
+}
+
+/***********************************************************************
+ * setidentifier : allocate 0-terminated string for identifier token
+ *
+ * Enter: tok = token, error given if not identifier
+ *
+ * Return: allocated 0-terminated string
+ */
+static char *
+setidentifier(struct tok *tok)
+{
+ char *s;
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected identifier");
+ s = memprintf("%.*s", tok->len, tok->start);
+ return s;
+}
+
+/***********************************************************************
+ * setargumentname : allocate 0-terminated string for identifier token
+ *
+ * Enter: tok = token, error given if not identifier
+ *
+ * Return: allocated 0-terminated string
+ */
+static char *
+setargumentname(struct tok *tok)
+{
+ char *s;
+ if (tok->type != TOK_IDENTIFIER && tok->type < TOK_attribute)
+ tokerrorexit(tok, "expected argument name");
+ s = memprintf("%.*s", tok->len, tok->start);
+ return s;
+}
+
+
+/* Prototypes for funcs that have a forward reference. */
+static struct node *parsetype(struct tok *tok);
+static struct node *parsedefaultvalue(struct tok *tok, struct node *parent);
+static struct node *parseuniontype(struct tok *tok);
+static struct node *parseargumentlist(struct tok *tok);
+static void parsedefinitions(struct tok *tok, struct node *parent);
+static struct node *parsetypesuffixstartingwitharray(struct tok *tok, struct node *node);
+
+/***********************************************************************
+ * parsescopedname : parse [53] ScopedName
+ *
+ * Enter: tok = next token
+ * name = name of attribute to put scoped name in
+ * ref = whether to enable enclosing of the name in <ref> in
+ * outputwidl
+ *
+ * Return: node struct for new attribute
+ * tok updated
+ */
+static struct node *
+parsescopedname(struct tok *tok, const char *name, int ref)
+{
+ const char *start = tok->start, *end;
+ struct node *node;
+ unsigned int len = 0;
+ char *s = memalloc(3);
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected identifier");
+ s = memrealloc(s, len + tok->len + 1);
+ memcpy(s + len, tok->start, tok->len);
+ len += tok->len;
+ end = tok->start + tok->len;
+ lexnocomment();
+ s[len] = 0;
+ node = newattr(name, s);
+ if (ref) {
+ node->start = start;
+ node->end = end;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsescopednamelist : parse [51] ScopedNameList
+ *
+ * Enter: tok = next token
+ * name = name of element for scoped name list
+ * name2 = name of element for entry in list
+ * comment = whether to attach documentation to each name
+ *
+ * Return: node for list of scoped names
+ * tok updated
+ */
+static struct node *
+parsescopednamelist(struct tok *tok, const char *name, const char *name2,
+ int comment)
+{
+ struct node *node = newelement(name);
+ for (;;) {
+ struct node *attr = parsescopedname(tok, "name", 1);
+ struct node *n = newelement(name2);
+ if (comment)
+ setcommentnode(n);
+ addnode(n, attr);
+ addnode(node, n);
+ if (tok->type != ',')
+ break;
+ lexnocomment();
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsereturntype : parse [50] ReturnType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsereturntype(struct tok *tok)
+{
+ if (tok->type == TOK_void) {
+ struct node *node = newelement("Type");
+ addnode(node, newattr("type", "void"));
+ lexnocomment();
+ return node;
+ }
+ return parsetype(tok);
+}
+
+/***********************************************************************
+ * parseunsignedintegertype : parse [46] UnsignedIntegerType
+ *
+ * Enter: tok = next token (one of "unsigned", "short" or "long")
+ *
+ * Return: 0-terminated canonical string for the type
+ * tok updated to just past UnsignedIntegerType
+ */
+static const char *
+parseunsignedintegertype(struct tok *tok)
+{
+ static const char *names[] = {
+ "short", "long", "long long", 0,
+ "unsigned short", "unsigned long", "unsigned long long" };
+ enum { TYPE_SHORT, TYPE_LONG, TYPE_LONGLONG,
+ TYPE_UNSIGNED = 4 };
+ int type = 0;
+ if (tok->type == TOK_unsigned) {
+ type = TYPE_UNSIGNED;
+ lexnocomment();
+ }
+ if (tok->type == TOK_short) {
+ type |= TYPE_SHORT;
+ lexnocomment();
+ } else if (tok->type != TOK_long)
+ tokerrorexit(tok, "expected 'short' or 'long' after 'unsigned'");
+ else {
+ type |= TYPE_LONG;
+ lexnocomment();
+ if (tok->type == TOK_long) {
+ type += TYPE_LONGLONG - TYPE_LONG;
+ lexnocomment();
+ }
+ }
+ return names[type];
+}
+/***********************************************************************
+ * parsetypesuffix : parse [44] TypeSuffix
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsetypesuffix(struct tok *tok, struct node *node)
+{
+ if (tok->type == TOK_DOUBLEBRACKET) {
+ struct node *typenode = node;
+ node = newelement("Type");
+ addnode(node, newattr("type", "array"));
+ addnode(node, typenode);
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ } else if (tok->type == '?') {
+ addnode(node, newattr("nullable", "nullable"));
+ lexnocomment();
+ node = parsetypesuffixstartingwitharray(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsetypesuffixstartingwitharray : parse [44] TypeSuffixStartingWithArray
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsetypesuffixstartingwitharray(struct tok *tok, struct node *node)
+{
+ if (tok->type == TOK_DOUBLEBRACKET) {
+ struct node *typenode = node;
+ node = newelement("Type");
+ addnode(node, newattr("type", "array"));
+ addnode(node, typenode);
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseprimitiveorstringtype : parse [45] PrimitiveOrString
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parseprimitiveorstringtype(struct tok *tok)
+{
+ struct node *node;
+ switch (tok->type) {
+ case TOK_unsigned:
+ case TOK_short:
+ case TOK_long:
+ node = newelement("Type");
+ addnode(node, newattr("type", parseunsignedintegertype(tok)));
+ break;
+ default:
+ node = newelement("Type");
+ switch (tok->type) {
+ default:
+ tokerrorexit(tok, "expected type");
+ break;
+ case TOK_unrestricted:
+ lexnocomment();
+ if (tok->type == TOK_float) {
+ addnode(node, newattr("type", "unrestricted float"));
+ } else if (tok->type == TOK_double) {
+ addnode(node, newattr("type", "unrestricted double"));
+ } else {
+ tokerrorexit(tok, "expected float or double after unrestricted");
+ }
+ break;
+ case TOK_boolean:
+ addnode(node, newattr("type", "boolean"));
+ break;
+ case TOK_byte:
+ addnode(node, newattr("type", "byte"));
+ break;
+ case TOK_octet:
+ addnode(node, newattr("type", "octet"));
+ break;
+ case TOK_float:
+ addnode(node, newattr("type", "float"));
+ break;
+ case TOK_double:
+ addnode(node, newattr("type", "double"));
+ break;
+ case TOK_DOMString:
+ addnode(node, newattr("type", "DOMString"));
+ break;
+ case TOK_ByteString:
+ addnode(node, newattr("type", "ByteString"));
+ break;
+ case TOK_Date:
+ addnode(node, newattr("type", "Date"));
+ break;
+ case TOK_RegExp:
+ addnode(node, newattr("type", "RegExp"));
+ break;
+
+ }
+ lexnocomment();
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsenonanytype : parse NonAnyType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsenonanytype(struct tok *tok)
+{
+ struct node *node;
+ switch (tok->type) {
+ case TOK_IDENTIFIER:
+ node = newelement("Type");
+ addnode(node, parsescopedname(tok, "name", 1));
+ node = parsetypesuffix(tok, node);
+ break;
+ case TOK_sequence:
+ node = newelement("Type");
+ addnode(node, newattr("type", "sequence"));
+ lexnocomment();
+ eat(tok, '<');
+ addnode(node, parsetype(tok));
+ eat(tok, '>');
+ if (tok->type == '?') {
+ addnode(node, newattr("nullable", "nullable"));
+ lexnocomment();
+ }
+ break;
+ case TOK_object:
+ node = newelement("Type");
+ addnode(node, newattr("type", "object"));
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ break;
+ default:
+ node = parseprimitiveorstringtype(tok);
+ node = parsetypesuffix(tok, node);
+ break;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseunionmembertype: parse UnionMemberType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parseunionmembertype(struct tok *tok)
+{
+ struct node *node;
+ if (tok->type == TOK_any) {
+ struct node *typenode = newelement("Type");
+ addnode(typenode, newattr("type", "any"));
+ lexnocomment();
+ eat(tok, TOK_DOUBLEBRACKET);
+ node = newelement("Type");
+ addnode(node, newattr("type", "array"));
+ addnode(node, typenode);
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ } else if (tok->type == '(') {
+ node = parseuniontype(tok);
+ } else {
+ node = parsenonanytype(tok);
+ }
+ return node;
+}
+
+
+/***********************************************************************
+ * parseuniontype : parse UnionType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parseuniontype(struct tok *tok)
+{
+ struct node *node;
+ eat(tok, '(');
+ node = newelement("Type");
+ addnode(node, newattr("type", "union"));
+ if (tok->type != ')') {
+ for (;;) {
+ addnode(node, parseunionmembertype(tok));
+ if (tok->type != TOK_or)
+ break;
+ lexnocomment();
+ }
+ }
+ eat(tok, ')');
+ node = parsetypesuffix(tok, node);
+ return node;
+}
+
+/***********************************************************************
+ * parsetype : parse [44] Type
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsetype(struct tok *tok)
+{
+ struct node *node;
+ if (tok->type == '(') {
+ node = parseuniontype(tok);
+ } else if (tok->type == TOK_any) {
+ node = newelement("Type");
+ addnode(node, newattr("type", "any"));
+ lexnocomment();
+ node = parsetypesuffixstartingwitharray(tok, node);
+ } else {
+ node = parsenonanytype(tok);
+ }
+ return node;
+}
+
+
+/***********************************************************************
+ * parseextendedattribute : parse [39] ExtendedAttribute
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for extended attribute
+ *
+ * This parses the various forms of extended attribute, as in
+ * rules [57] [58] [59] [60] [61].
+ *
+ * This does not spot the error that you cannot have a ScopedName
+ * and an ArgumentList.
+ */
+static struct node *
+parseextendedattribute(struct tok *tok)
+{
+ const char *start ;
+ struct node *node = newelement("ExtendedAttribute");
+ char *attrname = setidentifier(tok);
+ addnode(node, newattr("name", attrname));
+ start = tok->prestart;
+ node->wsstart = start;
+ node->end = tok->start + tok->len;
+ if(!strcmp(attrname, "Constructor") || !strcmp(attrname, "NamedConstructor")) {
+ setcommentnode(node);
+ }
+ lexnocomment();
+ if (tok->type == '=') {
+ lexnocomment();
+ addnode(node, parsescopedname(tok, "value", 0));
+ }
+ if (tok->type == '(') {
+ lexnocomment();
+ addnode(node, parseargumentlist(tok));
+ node->end = tok->start + tok->len;
+ eat(tok, ')');
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseextendedattributelist : parse [37] ExtendedAttributeList
+ *
+ * Enter: tok = next token
+ *
+ * Return: 0 else node for extended attribute list
+ * tok updated if anything parsed
+ */
+static struct node *
+parseextendedattributelist(struct tok *tok)
+{
+ struct node *node;
+ if (tok->type != '[')
+ return 0;
+ node = newelement("ExtendedAttributeList");
+ for (;;) {
+ lexnocomment();
+ addnode(node, parseextendedattribute(tok));
+ if (tok->type != ',')
+ break;
+ }
+ if (tok->type != ']')
+ tokerrorexit(tok, "expected ',' or ']'");
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseexceptionfield : parse [36] ExceptionField
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the exceptionfield
+ * tok updated
+ */
+static struct node *
+parseexceptionfield(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("ExceptionField");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, parsetype(tok));
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseargument : parse [31] Argument
+ *
+ * Enter: tok = next token
+ *
+ * Return: new node
+ *
+ * tok updated on return
+ */
+static struct node *
+parseargument(struct tok *tok)
+{
+ struct node *node = newelement("Argument");
+ struct node *eal = parseextendedattributelist(tok);
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ if (tok->type == TOK_optional) {
+ addnode(node, newattr("optional", "optional"));
+ lexnocomment();
+ }
+ addnode(node, parsetype(tok));
+ if (tok->type == TOK_ELLIPSIS) {
+ addnode(node, newattr("ellipsis", "ellipsis"));
+ lexnocomment();
+ }
+ addnode(node, newattr("name", setargumentname(tok)));
+ lexnocomment();
+ // Optional default value
+ if (tok->type == '=') {
+ tok = lexnocomment();
+ node = parsedefaultvalue(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseargumentlist : parse [29] ArgumentList
+ *
+ * Enter: tok = next token
+ *
+ * Return: new node for the arglist
+ * tok updated
+ */
+static struct node *
+parseargumentlist(struct tok *tok)
+{
+ struct node *node = newelement("ArgumentList");
+ /* We rely on the fact that ArgumentList is always followed by ')'. */
+ if (tok->type != ')') {
+ for (;;) {
+ addnode(node, parseargument(tok));
+ if (tok->type != ',')
+ break;
+ lexnocomment();
+ }
+ }
+ return node;
+}
+
+
+/***********************************************************************
+ * parseoperationrest : parse [25] OperationRest
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parseoperationrest(struct tok *tok, struct node *node)
+{
+ if (tok->type == TOK_IDENTIFIER) {
+ addnode(node, newattr("name", setidentifier(tok)));
+ lexnocomment();
+ }
+ eat(tok, '(');
+ addnode(node, parseargumentlist(tok));
+ eat(tok, ')');
+ return node;
+}
+
+/***********************************************************************
+ * parsereturntypeandoperationrest: parse ReturnType OperationRest
+ * Enter: tok = next token
+ * eal
+ * attrs list of attributes
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parsereturntypeandoperationrest(struct tok *tok, struct node *eal, struct node *attrs)
+{
+ struct node *node = newelement("Operation");
+ struct node *nodeType = parsereturntype(tok);
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, attrs);
+ addnode(node, nodeType);
+ return parseoperationrest(tok, node);
+}
+
+/***********************************************************************
+ * parseiteratorrest : parse OptionalIteratorInterface
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parseoptionaliteratorinterface(struct tok *tok, struct node *node)
+{
+ if (tok->type == '=') {
+ lexnocomment();
+ addnode(node, newattr("interface", setidentifier(tok)));
+ lexnocomment();
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseoperationoriteratorrest : parse [25] OperationOrIteratorRest
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ * attrs = list-of-attrs node containing attrs to add to new node
+ *
+ * Return: new node
+ * tok on terminating ';'
+ */
+static struct node *
+parseoperationoriteratorrest(struct tok *tok, struct node *eal, struct node *attrs)
+{
+ struct node *node;
+ struct node *nodeType = parsereturntype(tok);
+ unsigned int isIterator = 0;
+ if (tok->type == TOK_iterator) {
+ lexnocomment();
+ if (tok->type == TOK_object) {
+ lexnocomment();
+ node = newelement("IteratorObject");
+ addnode(node, nodeType);
+ return node;
+ } else {
+ node = newelement("Iterator");
+ isIterator = 1;
+ }
+ } else {
+ node = newelement("Operation");
+ }
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, attrs);
+ addnode(node, nodeType);
+ if (isIterator)
+ return parseoptionaliteratorinterface(tok, node);
+ else
+ return parseoperationrest(tok, node);
+}
+
+
+/***********************************************************************
+ * parseattribute : parse [17] Attribute
+ *
+ * Enter: tok = next token ("readonly" or "attribute")
+ * eal = 0 else extended attribute list node
+ * attrs = list-of-attrs node containing attrs to add to new node
+ *
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parseattribute(struct tok *tok, struct node *eal, struct node *attrs)
+{
+ struct node *node = newelement("Attribute");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, attrs);
+ if (tok->type == TOK_inherit) {
+ lexnocomment();
+ addnode(node, newattr("inherit", "inherit"));
+ }
+ if (tok->type == TOK_readonly) {
+ lexnocomment();
+ addnode(node, newattr("readonly", "readonly"));
+ }
+ eat(tok, TOK_attribute);
+ addnode(node, parsetype(tok));
+ addnode(node, newattr("name", setidentifier(tok)));
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseserializer : parse Serializer
+ *
+ * Enter: tok = next token
+ * eal
+ *
+ * Return: node updated with value
+ * tok updated
+ */
+static struct node *
+parseserializer (struct tok *tok, struct node *eal) {
+ struct node *nodeAttribute;
+ struct node *node = newelement("Serializer");
+ if (tok->type == '=') {
+ if (eal) addnode(node, eal);
+ lexnocomment();
+ if (tok->type == TOK_IDENTIFIER) {
+ addnode(node, newattr("attribute", setidentifier(tok)));
+ lexnocomment();
+ } else if (tok->type == '{') {
+ unsigned int done = 0;
+ struct node *nodeMap = newelement("Map");
+ lexnocomment();
+ if (tok->type == TOK_getter) {
+ addnode(nodeMap, newattr("pattern", "getter"));
+ done = 1;
+ } else if (tok->type == TOK_attribute) {
+ addnode(nodeMap, newattr("pattern", "all"));
+ done = 1;
+ } else if (tok->type == TOK_inherit) {
+ addnode(nodeMap, newattr("inherit", "inherit"));
+ lexnocomment();
+ eat(tok, ',');
+ if (tok->type == TOK_attribute) {
+ addnode(nodeMap, newattr("pattern", "all"));
+ done = 1;
+ }
+ } else if (tok->type != TOK_IDENTIFIER) {
+ tokerrorexit(tok, "expected 'attribute', 'getter', 'inherit' or attribute identifiers in serializer map");
+ }
+ if (done) {
+ lexnocomment();
+ eat(tok, '}');
+ } else {
+ addnode(nodeMap, newattr("pattern", "selection"));
+ do {
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected attribute identifiers in serializer map %s", tok->prestart);
+ nodeAttribute = newelement("PatternAttribute");
+ addnode(nodeAttribute, newattr("name", setidentifier(tok)));
+ addnode(nodeMap, nodeAttribute);
+ lexnocomment();
+ if (tok->type == ',')
+ lexnocomment();
+ } while (tok->type != '}');
+ eat(tok, '}');
+ }
+ addnode(node, nodeMap);
+ } else if (tok->type == '[') {
+ struct node *nodeList = newelement("List");
+ lexnocomment();
+ if (tok->type == TOK_getter) {
+ addnode(nodeList, newattr("pattern", "getter"));
+ lexnocomment();
+ eat(tok, ']');
+ } else {
+ addnode(nodeList, newattr("pattern", "selection"));
+ do {
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected attribute identifiers in serializer list");
+ nodeAttribute = newelement("PatternAttribute");
+ addnode(nodeAttribute, newattr("name", setidentifier(tok)));
+ addnode(nodeList, nodeAttribute);
+ lexnocomment();
+ if (tok->type == ',')
+ lexnocomment();
+ } while (tok->type != ']');
+ eat(tok, ']');
+ }
+ addnode(node, nodeList);
+ } else {
+ tokerrorexit(tok, "Expected '{', '[' or an attribute identifier in the serializer declaration");
+ }
+ return node;
+ } else {
+ if (eal) addnode(node, eal);
+ return node;
+ }
+}
+
+/***********************************************************************
+ * parseattributeoroperationoriterator : parse [15] AttributeOrOperationOrIterator
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node
+ * tok on terminating ';'
+ */
+static struct node *
+parseattributeoroperationoriterator(struct tok *tok, struct node *eal)
+{
+ int alreadyseen ;
+ struct node *attrs = newattrlist();
+ if (tok->type == TOK_serializer) {
+ lexnocomment();
+ if (tok->type == '=' || tok->type ==';') {
+ return parseserializer(tok, eal);
+ } else {
+ addnode(attrs, newattr("serializer", "serializer"));
+ return parsereturntypeandoperationrest(tok, eal, attrs);
+ }
+ }
+ if (tok->type == TOK_stringifier) {
+ addnode(attrs, newattr("stringifier", "stringifier"));
+ lexnocomment();
+ if (tok->type == ';') {
+ struct node *node = newelement("Stringifier");
+ if (eal) addnode(node, eal);
+ return node;
+ }
+ }
+ if (tok->type == TOK_static) {
+ lexnocomment();
+ addnode(attrs, newattr("static", "static"));
+ }
+ if (tok->type == TOK_inherit || tok->type == TOK_readonly || tok->type == TOK_attribute)
+ return parseattribute(tok, eal, attrs);
+ if (!nodeisempty(attrs))
+ return parsereturntypeandoperationrest(tok, eal, attrs);
+ alreadyseen = 0;
+ for (;;) {
+ static const int t[] = { TOK_getter,
+ TOK_setter, TOK_creator, TOK_deleter, TOK_legacycaller,
+ 0 };
+ const int *tt = t;
+ char *s;
+ while (*tt && *tt != tok->type)
+ tt++;
+ if (!*tt)
+ break;
+ s = memprintf("%.*s", tok->len, tok->start);
+ if (alreadyseen & (1 << (tt - t)))
+ tokerrorexit(tok, "'%s' qualifier cannot be repeated", s);
+ alreadyseen |= 1 << (tt - t);
+ addnode(attrs, newattr(s, s));
+ lexnocomment();
+ }
+ if (!nodeisempty(attrs))
+ return parsereturntypeandoperationrest(tok, eal, attrs);
+ else
+ return parseoperationoriteratorrest(tok, eal, attrs);
+}
+
+
+/***********************************************************************
+ * parseconstexpr : parse ConstValue
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node updated with value
+ * tok updated
+ */
+static struct node *
+parseconstexpr (struct tok *tok, struct node *node) {
+ char *s;
+ switch(tok->type) {
+ case TOK_true:
+ case TOK_false:
+ case TOK_minusinfinity:
+ case TOK_INTEGER:
+ case TOK_FLOAT:
+ case TOK_null:
+ case TOK_infinity:
+ case TOK_NaN:
+ break;
+ default:
+ tokerrorexit(tok, "expected constant value");
+ break;
+ }
+ s = memalloc(tok->len + 1);
+ memcpy(s, tok->start, tok->len);
+ s[tok->len] = 0;
+ if (tok->type != TOK_STRING) {
+ addnode(node, newattr("value", s));
+ } else {
+ addnode(node, newattr("stringvalue", s));
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parsedefaultvalue : parse DefaultValue
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node updated with value
+ * tok updated
+ */
+static struct node *
+parsedefaultvalue (struct tok *tok, struct node *node) {
+ char *s;
+ if (tok->type == TOK_STRING) {
+ s = memalloc(tok->len + 1);
+ memcpy(s, tok->start, tok->len);
+ s[tok->len] = 0;
+ addnode(node, newattr("stringvalue", s));
+ lexnocomment();
+ return node;
+ } else {
+ return parseconstexpr(tok, node);
+ }
+}
+
+
+
+/***********************************************************************
+ * parsedictionarymember : parse DictionaryMember
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node
+ * tok on terminating ';'
+ */
+static struct node *
+parsedictionarymember(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("DictionaryMember");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, parsetype(tok));
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ // Optional value
+ if (tok->type == '=') {
+ tok = lexnocomment();
+ node = parsedefaultvalue(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseconst : parse [12] Const
+ *
+ * Enter: tok = next token, known to be TOK_const
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the const
+ * tok on terminating ';'
+ */
+static struct node *
+parseconst(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Const");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ tok = lexnocomment();
+ switch(tok->type) {
+ case TOK_boolean:
+ case TOK_byte:
+ case TOK_octet:
+ case TOK_float:
+ case TOK_double:
+ case TOK_unsigned:
+ case TOK_unrestricted:
+ case TOK_short:
+ case TOK_long:
+ addnode(node, parsetype(tok));
+ break;
+ default:
+ tokerrorexit(tok, "expected acceptable constant type");
+ break;
+ }
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ eat(tok, '=');
+ node = parseconstexpr(tok, node);
+ return node;
+}
+
+/***********************************************************************
+ * parseimplementsstatement : parse [11] ImplementsStatement
+ *
+ * Enter: tok = next token, known to be :: or TOK_IDENTIFIER
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the typedef
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseimplementsstatement(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Implements");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ addnode(node, parsescopedname(tok, "name1", 1));
+ eat(tok, TOK_implements);
+ addnode(node, parsescopedname(tok, "name2", 1));
+ return node;
+}
+
+/***********************************************************************
+ * parsetypedef : parse [10] Typedef
+ *
+ * Enter: tok = next token, known to be TOK_typedef
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the typedef
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parsetypedef(struct tok *tok, struct node *eal)
+{
+struct node *ealtype;
+struct node *typenode;
+ struct node *node = newelement("Typedef");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ tok = lexnocomment();
+ ealtype = parseextendedattributelist(tok);
+ typenode = parsetype(tok);
+ if (ealtype) addnode(typenode, ealtype);
+ addnode(node, typenode);
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseexception : parse [8] Exception
+ *
+ * Enter: tok = next token, known to be TOK_exception
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the exception
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseexception(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Exception");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ lexnocomment();
+ if (tok->type == ':') {
+ lexnocomment();
+ addnode(node, parsescopednamelist(tok, "ExceptionInheritance", "Name", 1));
+ }
+ eat(tok, '{');
+ while (tok->type != '}') {
+ const char *start = tok->prestart;
+ struct node *node2;
+ struct node *eal = parseextendedattributelist(tok);
+ if (tok->type == TOK_const)
+ node2 = parseconst(tok, eal);
+ else
+ node2 = parseexceptionfield(tok, eal);
+ addnode(node, node2);
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ eat(tok, ';');
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseinterface : parse [4] Interface
+ *
+ * Enter: tok = next token, known to be TOK_interface
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the interface
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseinterface(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Interface");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ if (tok->type == ':') {
+ lexnocomment();
+ addnode(node, parsescopednamelist(tok, "InterfaceInheritance", "Name", 1));
+ }
+ eat(tok, '{');
+ while (tok->type != '}') {
+ const char *start = tok->prestart;
+ struct node *eal = parseextendedattributelist(tok);
+ struct node *node2;
+ if (tok->type == TOK_const)
+ addnode(node, node2 = parseconst(tok, eal));
+ else
+ addnode(node, node2 = parseattributeoroperationoriterator(tok, eal));
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ eat(tok, ';');
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parsecallback : parse Callback
+ *
+ * Enter: tok = next token, known to be TOK_dictionary
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the enum
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parsecallback(struct tok *tok, struct node *eal)
+{
+ struct node *node;
+ if (tok->type == TOK_interface) {
+ node = parseinterface(tok, eal);
+ addnode(node, newattr("callback", "callback"));
+ } else {
+ node = newelement("Callback");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ eat(tok, '=');
+ addnode(node, parsereturntype(tok));
+ eat(tok, '(');
+ addnode(node, parseargumentlist(tok));
+ eat(tok, ')');
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsedictionary : parse Dictionary
+ *
+ * Enter: tok = next token, known to be TOK_dictionary
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the dictionary
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parsedictionary(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Dictionary");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ if (tok->type == ':') {
+ lexnocomment();
+ addnode(node, parsescopednamelist(tok, "DictionaryInheritance", "Name", 1));
+ }
+ eat(tok, '{');
+ while (tok->type != '}') {
+ const char *start = tok->prestart;
+ struct node *eal = parseextendedattributelist(tok);
+ struct node *node2;
+ if (tok->type == TOK_const)
+ addnode(node, node2 = parseconst(tok, eal));
+ else
+ addnode(node, node2 = parsedictionarymember(tok, eal));
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ eat(tok, ';');
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseenum : parse Enum
+ *
+ * Enter: tok = next token, known to be TOK_dictionary
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the enum
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseenum(struct tok *tok, struct node *eal)
+{
+ char *s;
+ struct node *node = newelement("Enum");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ eat(tok, '{');
+ while (tok->type != '}') {
+ if (tok->type == TOK_STRING) {
+ const char *start = tok->prestart;
+ struct node *node2 = newelement("EnumValue");
+ setcommentnode(node2);
+
+ s = memalloc(tok->len + 1);
+ memcpy(s, tok->start, tok->len);
+ s[tok->len] = 0;
+ addnode(node2, newattr("stringvalue", s));
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ addnode(node, node2);
+ } else {
+ tokerrorexit(tok, "expected string in enum");
+ }
+ lexnocomment();
+ if (tok->type == ',') {
+ lexnocomment();
+ }
+ }
+ eat(tok, '}');
+ return node;
+}
+
+/***********************************************************************
+ * parsedefinitions : parse [1] Definitions
+ *
+ * Enter: tok = next token
+ * parent = parent node to add definitions to
+ *
+ * On return, tok has been updated.
+ */
+static void
+parsedefinitions(struct tok *tok, struct node *parent)
+{
+ parent->wsstart = tok->prestart;
+ for (;;) {
+ const char *wsstart = tok->prestart;
+ struct node *eal = parseextendedattributelist(tok);
+ struct node *node;
+ switch (tok->type) {
+ case TOK_partial:
+ eat(tok, TOK_partial);
+ if (tok->type == TOK_dictionary) {
+ node = parsedictionary(tok, eal);
+ } else {
+ node = parseinterface(tok, eal);
+ }
+ addnode(node, newattr("partial", "partial"));
+ break;
+ case TOK_interface:
+ node = parseinterface(tok, eal);
+ break;
+ case TOK_callback:
+ eat(tok, TOK_callback);
+ node = parsecallback(tok, eal);
+ break;
+ case TOK_dictionary:
+ node = parsedictionary(tok, eal);
+ break;
+ case TOK_enum:
+ node = parseenum(tok, eal);
+ break;
+ case TOK_exception:
+ node = parseexception(tok, eal);
+ break;
+ case TOK_typedef:
+ node = parsetypedef(tok, eal);
+ break;
+ case TOK_IDENTIFIER:
+ node = parseimplementsstatement(tok, eal);
+ break;
+ default:
+ if (eal)
+ tokerrorexit(tok, "expected definition after extended attribute list");
+ node = 0;
+ break;
+ }
+ if (!node)
+ break;
+ node->wsstart = wsstart;
+ node->end = tok->start + tok->len;
+ eat(tok, ';');
+ addnode(parent, node);
+ setid(node);
+ parent->end = node->end;
+ }
+}
+
+/***********************************************************************
+ * parse
+ *
+ * Return: root element containing (possibly empty) list of definitions
+ */
+struct node *
+parse(void)
+{
+ struct tok *tok;
+ struct node *root = newelement("Definitions");
+ setcommentnode(root);
+ tok = lexnocomment();
+ parsedefinitions(tok, root);
+ if (tok->type != TOK_EOF)
+ tokerrorexit(tok, "expected end of input");
+ reversechildren(root);
+ return root;
+}
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.h
new file mode 100644
index 000000000..ad9071b45
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/parse.h
@@ -0,0 +1,19 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef parse_h
+#define parse_h
+
+struct node *parse(void);
+
+#endif /* ndef parse_h */
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.c b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.c
new file mode 100644
index 000000000..d6a343b8a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.c
@@ -0,0 +1,319 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "comment.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "os.h"
+#include "parse.h"
+#include "process.h"
+
+#if 0
+static const char ntnames[] = { NTNAMES };
+#endif /*0*/
+
+/***********************************************************************
+ * printtext : print text with xml entity escapes
+ *
+ * Enter: s = text
+ * len = number of bytes
+ * escamp = whether to escape &
+ *
+ * This also escapes double quote mark so it can be used for an
+ * attribute value. It also turns a tab into spaces.
+ */
+void
+printtext(const char *s, unsigned int len, int escamp)
+{
+ const char *p = s, *end = s + len;
+ unsigned int count = 0;
+ while (p != end) {
+ int ch = *p;
+ char buf[9];
+ const char *seq = 0;
+ count++;
+ switch (ch) {
+ case '<':
+ seq = "&lt;";
+ break;
+ case '&':
+ seq = escamp ? "&amp;" : "&";
+ break;
+ case '"':
+ seq = "&quot;";
+ break;
+ case '\n':
+ p++;
+ count = 0;
+ continue;
+ case '\t':
+ seq = " " + ((count - 1) & 7);
+ count = 0;
+ break;
+ default:
+ if ((unsigned char)ch >= 0x20) {
+ p++;
+ continue;
+ }
+ snprintf(buf, 9, "&#%i;", ch);
+ seq = buf;
+ break;
+ }
+ if (p - s != fwrite(s, 1, p - s, stdout))
+ errorexit("write error");
+ fputs(seq, stdout);
+ s = ++p;
+ }
+ if (p - s != fwrite(s, 1, p - s, stdout))
+ errorexit("write error");
+}
+
+#if 0
+/***********************************************************************
+ * outputnodeastext : output parse node and descendants as deparsed text
+ *
+ * Enter: node = parse node
+ * needspace = true if last output char was an identifier char
+ *
+ * Return: updated needspace value
+ */
+static int
+outputnodeastext(struct node *node, int needspace)
+{
+ if (node->type >= NT_START) {
+ struct node *child = node->children;
+ while (child) {
+ needspace = outputnodeastext(child, needspace);
+ child = child->next;
+ }
+ } else {
+ unsigned int len = strlen(node->name);
+ if (len) {
+ int ch = node->name[0];
+ if (ch == '_' || ((unsigned)(ch - '0') < 10
+ || (unsigned)((ch & ~0x20) - 'A') < 26))
+ {
+ if (needspace) putchar(' ');
+ }
+ ch = node->name[len - 1];
+ if (ch == '_' || ((unsigned)(ch - '0') < 10
+ || (unsigned)((ch & ~0x20) - 'A') < 26))
+ {
+ needspace = 1;
+ }
+ printtext(node->name, len, 1);
+ }
+ }
+ return needspace;
+}
+
+/***********************************************************************
+ * printfqid : print fully-qualified id
+ *
+ * Enter: node struct
+ *
+ * Return: whether anything printed
+ */
+static int
+printfqid(struct node *node)
+{
+ int any = 0;
+ struct node *identifier;
+ if (node->parent) {
+ any = printfqid(node->parent);
+ }
+ switch (node->type) {
+ case NT_Module:
+ case NT_Interface:
+ case NT_Typedef:
+ case NT_Operation:
+ case NT_Attribute:
+ case NT_Const:
+ if (any)
+ printf(":");
+ /* Find identifier child if any. */
+ identifier = node->children;
+ while (identifier) {
+ if (identifier->type == TOK_IDENTIFIER)
+ break;
+ if (identifier->type == NT_TypedefRest) {
+ identifier = identifier->children;
+ continue;
+ }
+ identifier = identifier->next;
+ }
+ if (identifier) {
+ printtext(identifier->name, strlen(identifier->name), 1);
+ any = 1;
+ }
+ break;
+ }
+ return any;
+}
+
+/***********************************************************************
+ * output : output subtree of parse tree
+ *
+ * Enter: node = root of subtree
+ * extendedattributelist = 0 else extended attribute list node
+ * applying to node
+ * indent = indent (nesting) level
+ */
+static void outputchildren(struct node *node, struct node *identifier, unsigned int indent);
+
+static void
+output(struct node *node, struct node *extendedattributelist,
+ unsigned int indent)
+{
+ if (extendedattributelist) {
+ node->wsstart = extendedattributelist->wsstart;
+ node->start = extendedattributelist->start;
+ }
+ if (node->type == NT_ExtendedAttribute) {
+ printf("%*s<ExtendedAttribute value=\"", indent, "");
+ outputnodeastext(node, 0);
+ printf("\"/>\n");
+ } else if (node->type == NT_BooleanLiteral) {
+ printf("%*s<BooleanLiteral value=\"%s\"/>", indent, "",
+ node->children->name);
+ } else if (node->type == NT_ReadOnly) {
+ printf("%*s<ReadOnly/>\n", indent, "");
+ } else if (node->type >= NT_START) {
+ const char *ntname;
+ /* Find identifier child if any. */
+ struct node *identifier = node->children;
+ while (identifier) {
+ if (identifier->type == TOK_IDENTIFIER)
+ break;
+ identifier = identifier->next;
+ }
+ /* Find nonterminal name. */
+ ntname = ntnames + 2;
+ while (node->type - NT_START != ((unsigned char)ntname[-2] | (unsigned char)ntname[-1] << 8))
+ ntname += strlen(ntname) + 3;
+ /* Output start of element. */
+ printf("%*s<%s", indent, "", ntname);
+ /* Output identifier if any as attribute. */
+ if (identifier) {
+ printf(" identifier=\"");
+ printtext(identifier->name, strlen(identifier->name), 1);
+ printf("\"");
+ }
+ switch (node->type) {
+ case NT_Module:
+ case NT_Interface:
+ case NT_Typedef:
+ case NT_Const:
+ /* Output fully qualified id. */
+ printf(" fqid=\"");
+ printfqid(node);
+ printf("\"");
+ break;
+ }
+ if (!identifier && !extendedattributelist && !node->children && !node->comments)
+ printf("/>\n");
+ else {
+ printf(">\n");
+ /* Output descriptive elements (doxygen comments) for node. */
+ outputdescriptive(node, indent + 2);
+ /* Output descriptive elements (doxygen comments) for identifier. */
+ if (identifier)
+ outputdescriptive(identifier, indent + 2);
+ /* Output extended attribute list. */
+ if (extendedattributelist)
+ output(extendedattributelist, 0, indent + 2);
+ /* Output children (excluding identifier child). */
+ outputchildren(node, identifier, indent + 2);
+ printf("%*s</%s>\n", indent, "", ntname);
+ }
+ } else switch (node->type) {
+ case TOK_DOMString:
+ case TOK_any:
+ case TOK_boolean:
+ case TOK_octet:
+ case TOK_float:
+ case TOK_double:
+ case TOK_Object:
+ case TOK_unsigned:
+ case TOK_short:
+ case TOK_long:
+ case TOK_void:
+ printf("%*s<%s/>\n", indent, "", node->name);
+ break;
+ case TOK_INTEGER:
+ printf("%*s<integer value=\"", indent, "");
+ printtext(node->name, strlen(node->name), 1);
+ printf("\"/>\n");
+ break;
+ case TOK_FLOAT:
+ printf("%*s<Float value=\"", indent, "");
+ printtext(node->name, strlen(node->name), 1);
+ printf("\"/>\n");
+ break;
+ case TOK_STRING:
+ printf("%*s<string value=\"", indent, "");
+ printtext(node->name, strlen(node->name), 1);
+ printf("\"/>\n");
+ break;
+ }
+}
+
+/***********************************************************************
+ * outputchildren : call output for each child of node
+ *
+ * Enter: node
+ * identifier = child node to omit from output
+ * indent = indent (nesting) level
+ */
+static void
+outputchildren(struct node *node, struct node *identifier, unsigned int indent)
+{
+ struct node *extendedattributelist;
+ struct node *child;
+ child = node->children;
+ extendedattributelist = 0;
+ while (child) {
+ if (child->type == NT_ExtendedAttributeList && node->type != NT_Argument)
+ extendedattributelist = child;
+ else {
+ if (identifier != child)
+ output(child, extendedattributelist, indent);
+ extendedattributelist = 0;
+ }
+ child = child->next;
+ }
+}
+#endif /*0*/
+
+/***********************************************************************
+ * processfiles : process input files
+ *
+ * Enter: name = filename
+ */
+void
+processfiles(const char *const *names, int dtdref)
+{
+ struct node *root;
+ readinput(names);
+ root = parse();
+ processcomments(root);
+ printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ if(dtdref)
+ printf("<!DOCTYPE Definitions SYSTEM \"widlprocxml.dtd\">\n");
+ outputnode(root, 0);
+}
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.h b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.h
new file mode 100644
index 000000000..bb92b22ce
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/process.h
@@ -0,0 +1,27 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef process_h
+#define process_h
+
+#if 0
+#define NT_START 0x100
+#include "nonterminals.h"
+#endif/*0*/
+
+void printtext(const char *s, unsigned int len, int escamp);
+
+void processfiles(const char *const *names, int dtdref);
+
+#endif /* ndef process_h */
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl
new file mode 100644
index 000000000..2b583371e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl
@@ -0,0 +1,828 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--====================================================================
+$Id: widlprocxmltohtml.xsl 407 2009-10-26 13:48:48Z tpr $
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+XSLT stylesheet to convert widlprocxml into html documentation.
+=====================================================================-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="html" encoding="utf-8" indent="yes" doctype-public="html"/>
+
+<xsl:param name="date" select="'error: missing date'"/>
+
+<xsl:variable name="title" select="concat('The ',/Definitions/descriptive/name,' Module - Version ',/Definitions/descriptive/version)"/>
+
+<!--Root of document.-->
+<xsl:template match="/">
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="widlhtml.css" media="screen"/>
+ <title>
+ <xsl:value-of select="$title"/>
+ </title>
+ </head>
+ <body>
+ <xsl:apply-templates/>
+ </body>
+ </html>
+</xsl:template>
+
+<!--Root of Definitions.-->
+<xsl:template match="Definitions">
+ <div class="api" id="{@id}">
+ <a href="http://bondi.omtp.org"><img src="http://www.omtp.org/images/BondiSmall.jpg" alt="Bondi logo"/></a>
+ <h1><xsl:value-of select="$title"/></h1>
+ <h3>12 May 2009</h3>
+
+ <h2>Authors</h2>
+ <ul class="authors">
+ <xsl:apply-templates select="descriptive/author"/>
+ </ul>
+
+ <p class="copyright"><small>© The authors, 2012. All rights reserved.</small></p>
+
+ <hr/>
+
+ <h2>Abstract</h2>
+
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive/description"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+
+ <h2>Table of Contents</h2>
+ <ul class="toc">
+ <li><a href="#intro">Introduction</a>
+ <ul>
+ <xsl:if test="descriptive/def-api-feature-set">
+ <li><a href="#def-api-feature-sets">Feature set</a></li>
+ </xsl:if>
+ <xsl:if test="descriptive/def-api-feature">
+ <li><a href="#def-api-features">Features</a></li>
+ </xsl:if>
+ <xsl:if test="descriptive/def-device-cap">
+ <li><a href="#def-device-caps">Device Capabilities</a></li>
+ </xsl:if>
+ </ul>
+ </li>
+ <xsl:if test="Typedef">
+ <li><a href="#typedefs">Type Definitions</a>
+ <ul class="toc">
+ <xsl:for-each select="Typedef[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Interface">
+ <li><a href="#interfaces">Interfaces</a>
+ <ul class="toc">
+ <xsl:for-each select="Interface[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Dictionary">
+ <li><a href="#dictionaries">Dictionary types</a>
+ <ul class="toc">
+ <xsl:for-each select="Dictionary[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Callback">
+ <li><a href="#callbacks">Callbacks</a>
+ <ul class="toc">
+ <xsl:for-each select="Callback[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Enum">
+ <li><a href="#enums">Enums</a>
+ <ul class="toc">
+ <xsl:for-each select="Enum[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ </ul>
+
+ <hr/>
+
+ <h2>Summary of Methods</h2>
+ <xsl:call-template name="summary"/>
+
+ <h2 id="intro">Introduction</h2>
+
+ <xsl:apply-templates select="descriptive/description"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+
+ <xsl:if test="descriptive/def-api-feature-set">
+ <div id="def-api-feature-sets" class="def-api-feature-sets">
+ <h3 id="features">Feature set</h3>
+ <p>This is the URI used to declare this API's feature set, for use in bondi.requestFeature. For the URL, the list of features included by the feature set is provided.</p>
+ <xsl:apply-templates select="descriptive/def-api-feature-set"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="descriptive/def-api-feature">
+ <div id="def-api-features" class="def-api-features">
+ <h3 id="features">Features</h3>
+ <p>This is the list of URIs used to declare this API's features, for use in bondi.requestFeature. For each URL, the list of functions covered is provided.</p>
+ <xsl:apply-templates select="Interface/descriptive/def-instantiated"/>
+ <xsl:apply-templates select="descriptive/def-api-feature"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="descriptive/def-device-cap">
+ <div class="def-device-caps" id="def-device-caps">
+ <h3>Device capabilities</h3>
+ <dl>
+ <xsl:apply-templates select="descriptive/def-device-cap"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Typedef">
+ <div class="typedefs" id="typedefs">
+ <h2>Type Definitions</h2>
+ <xsl:apply-templates select="Typedef[descriptive]"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Interface">
+ <div class="interfaces" id="interfaces">
+ <h2>Interfaces</h2>
+ <xsl:apply-templates select="Interface"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Dictionary">
+ <div class="dictionaries" id="dictionaries">
+ <h2>Dictionary types</h2>
+ <xsl:apply-templates select="Dictionary"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Callback">
+ <div class="callbacks" id="callbacks">
+ <h2>Callbacks</h2>
+ <xsl:apply-templates select="Callback"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Enum">
+ <div class="enums" id="enums">
+ <h2>Enums</h2>
+ <xsl:apply-templates select="Enum"/>
+ </div>
+ </xsl:if>
+ </div>
+</xsl:template>
+
+<!--def-api-feature-set-->
+<xsl:template match="def-api-feature-set">
+ <dl class="def-api-feature-set">
+ <dt><xsl:value-of select="@identifier"/></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:if test="descriptive/api-feature">
+ <div class="api-features">
+ <p>
+ Includes API features:
+ </p>
+ <ul>
+ <xsl:for-each select="descriptive/api-feature">
+ <li><code><xsl:value-of select="@identifier"/></code></li>
+ </xsl:for-each>
+ </ul>
+ </div>
+ </xsl:if>
+ </dd>
+ </dl>
+</xsl:template>
+
+<!--def-api-feature-->
+<xsl:template match="def-api-feature">
+ <dl class="def-api-feature">
+ <dt><xsl:value-of select="@identifier"/></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:if test="descriptive/device-cap">
+ <div class="device-caps">
+ <p>
+ Device capabilities:
+ </p>
+ <ul>
+ <xsl:for-each select="descriptive/device-cap">
+ <li><code><xsl:value-of select="@identifier"/></code></li>
+ </xsl:for-each>
+ </ul>
+ </div>
+ </xsl:if>
+ </dd>
+ </dl>
+</xsl:template>
+
+<!--def-device-cap-->
+<xsl:template match="def-device-cap">
+ <dt class="def-device-cap"><code><xsl:value-of select="@identifier"/></code></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:if test="descriptive/param">
+ <div class="device-caps">
+ <p>Security parameters:</p>
+ <ul>
+ <xsl:apply-templates select="descriptive/param"/>
+ </ul>
+ </div>
+ </xsl:if>
+ </dd>
+</xsl:template>
+
+<!--Exception: not implemented-->
+<!--Valuetype: not implemented-->
+<xsl:template match="Exception|Valuetype|Const">
+ <xsl:if test="descriptive">
+ <xsl:message terminate="yes">element <xsl:value-of select="name()"/> not supported</xsl:message>
+ </xsl:if>
+</xsl:template>
+
+<!--Typedef.-->
+<xsl:template match="Typedef[descriptive]">
+ <div class="typedef" id="{@id}">
+ <h3>2.<xsl:number value="position()"/>. <code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </div>
+</xsl:template>
+
+<!--Interface.-->
+<xsl:template match="Interface[descriptive]">
+ <xsl:variable name="name" select="@name"/>
+ <div class="interface" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="../Implements[@name2=$name]/webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:apply-templates select="InterfaceInheritance"/>
+ <xsl:if test="Const/descriptive">
+ <div class="consts">
+ <h4>Constants</h4>
+ <dl>
+ <xsl:apply-templates select="Const"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="ExtendedAttributeList/ExtendedAttribute/descriptive">
+ <div class="constructors">
+ <h4>Constructors</h4>
+ <dl>
+ <xsl:apply-templates select="ExtendedAttributeList/ExtendedAttribute"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Attribute/descriptive">
+ <div class="attributes">
+ <h4>Attributes</h4>
+ <dl>
+ <xsl:apply-templates select="Attribute"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Operation/descriptive">
+ <div class="methods">
+ <h4>Methods</h4>
+ <dl>
+ <xsl:apply-templates select="Operation"/>
+ </dl>
+ </div>
+ </xsl:if>
+ </div>
+</xsl:template>
+<xsl:template match="Interface[not(descriptive)]">
+</xsl:template>
+
+<!--Dictionary.-->
+<xsl:template match="Dictionary[descriptive]">
+ <xsl:variable name="name" select="@name"/>
+ <div class="dictionary" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:apply-templates select="InterfaceInheritance"/>
+ <xsl:if test="Const/descriptive">
+ <div class="consts">
+ <h4>Constants</h4>
+ <dl>
+ <xsl:apply-templates select="Const"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Attribute/descriptive">
+ <div class="attributes">
+ <h4>Attributes</h4>
+ <dl>
+ <xsl:apply-templates select="Attribute"/>
+ </dl>
+ </div>
+ </xsl:if>
+ </div>
+</xsl:template>
+<xsl:template match="Dictionary[not(descriptive)]">
+</xsl:template>
+
+<xsl:template match="InterfaceInheritance/ScopedNameList">
+ <p>
+ <xsl:text>This interface inherits from: </xsl:text>
+ <xsl:for-each select="Name">
+ <code><xsl:value-of select="@name"/></code>
+ <xsl:if test="position!=last()">, </xsl:if>
+ </xsl:for-each>
+ </p>
+</xsl:template>
+
+<!--Attribute-->
+<xsl:template match="Attribute">
+ <dt class="attribute" id="{@name}">
+ <code>
+ <xsl:if test="@stringifier">
+ stringifier
+ </xsl:if>
+ <xsl:if test="@readonly">
+ readonly
+ </xsl:if>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ </code></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="GetRaises"/>
+ <xsl:apply-templates select="SetRaises"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--Const-->
+<xsl:template match="Const">
+ <dt class="const" id="{@id}">
+ <code>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--ExtendedAttribute name==Constructor || name==NamedConstructor-->
+<xsl:template match="ExtendedAttributeList/ExtendedAttribute">
+ <dt class="constructor" id="{concat(@name,generate-id(.))}">
+ <code>
+ <xsl:value-of select="../../@name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates select="ArgumentList">
+ <xsl:with-param name="nodesc" select="1"/>
+ </xsl:apply-templates>
+ <xsl:text>);</xsl:text>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="ArgumentList"/>
+ <xsl:apply-templates select="Raises"/>
+ <xsl:if test="descriptive/api-feature">
+ <div class="api-features">
+ <h6>API features</h6>
+ <dl>
+ <xsl:apply-templates select="descriptive/api-feature"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--Operation-->
+<xsl:template match="Operation">
+ <dt class="method" id="{concat(@name,generate-id(.))}">
+ <code>
+ <xsl:if test="@stringifier">
+ <xsl:value-of select="concat(@stringifier, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@omittable">
+ <xsl:value-of select="concat(@omittable, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@getter">
+ <xsl:value-of select="concat(@getter, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@setter">
+ <xsl:value-of select="concat(@setter, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@creator">
+ <xsl:value-of select="concat(@creator, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@deleter">
+ <xsl:value-of select="concat(@deleter, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@caller">
+ <xsl:value-of select="concat(@caller, ' ')"/>
+ </xsl:if>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates select="ArgumentList">
+ <xsl:with-param name="nodesc" select="1"/>
+ </xsl:apply-templates>
+ <xsl:text>);</xsl:text>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="ArgumentList"/>
+ <xsl:if test="Type/descriptive">
+ <div class="returntype">
+ <h5>Return value</h5>
+ <xsl:apply-templates select="Type/descriptive"/>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="Raises"/>
+ <xsl:if test="descriptive/api-feature">
+ <div class="api-features">
+ <h6>API features</h6>
+ <dl>
+ <xsl:apply-templates select="descriptive/api-feature"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--Callback-->
+<xsl:template match="Callback">
+ <xsl:variable name="name" select="@name"/>
+ <div class="callback" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <div class="synopsis">
+ <h6>Signature</h6>
+ <pre>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates select="ArgumentList">
+ <xsl:with-param name="nodesc" select="1"/>
+ </xsl:apply-templates>
+ <xsl:text>);
+</xsl:text></pre>
+ </div>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="ArgumentList"/>
+ <xsl:if test="Type/descriptive">
+ <div class="returntype">
+ <h5>Return value</h5>
+ <xsl:apply-templates select="Type/descriptive"/>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+ </div>
+</xsl:template>
+
+<!--ArgumentList. This is passed $nodesc=true to output just the argument
+ types and names, and not any documentation for them.-->
+<xsl:template match="ArgumentList">
+ <xsl:param name="nodesc"/>
+ <xsl:choose>
+ <xsl:when test="$nodesc">
+ <!--$nodesc is true: just output the types and names-->
+ <xsl:apply-templates select="Argument[1]">
+ <xsl:with-param name="nodesc" select="'nocomma'"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="Argument[position() != 1]">
+ <xsl:with-param name="nodesc" select="'comma'"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="Argument">
+ <!--$nodesc is false: output the documentation-->
+ <div class="parameters">
+ <h6>Parameters</h6>
+ <ul>
+ <xsl:apply-templates/>
+ </ul>
+ </div>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<!--Argument. This is passed $nodesc=false to output the documentation,
+ or $nodesc="nocomma" to output the type and name, or $nodesc="comma"
+ to output a comma then the type and name. -->
+<xsl:template match="Argument">
+ <xsl:param name="nodesc"/>
+ <xsl:choose>
+ <xsl:when test="$nodesc">
+ <!--$nodesc is true: just output the types and names-->
+ <xsl:if test="$nodesc = 'comma'">
+ <!--Need a comma first.-->
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ <xsl:if test="@in"><xsl:value-of select="concat(@in, ' ')"/></xsl:if>
+ <xsl:if test="@optional"><xsl:value-of select="concat(@optional, ' ')"/></xsl:if>
+ <xsl:apply-templates select="Type"/>
+ <xsl:if test="@ellipsis"><xsl:text>...</xsl:text></xsl:if>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:if test="@value">
+ <xsl:text>Default value: </xsl:text><xsl:value-of select="@value"/>
+ </xsl:if>
+ <xsl:if test="@stringvalue">
+ <xsl:text>Default value: "</xsl:text><xsl:value-of select="@stringvalue"/><xsl:text>"</xsl:text>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--$nodesc is false: output the documentation-->
+ <li class="param">
+ <xsl:value-of select="@name"/>:
+ <xsl:apply-templates select="descriptive"/>
+ </li>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--Raises (for an Operation). It is already known that the list
+ is not empty.-->
+<xsl:template match="Raises">
+ <div class="exceptionlist">
+ <h5>Exceptions</h5>
+ <ul>
+ <xsl:apply-templates/>
+ </ul>
+ </div>
+</xsl:template>
+
+<!--RaiseException, the name of an exception in a Raises.-->
+<xsl:template match="RaiseException">
+ <li class="exception">
+ <xsl:value-of select="@name"/>:
+ <xsl:apply-templates select="descriptive"/>
+ </li>
+</xsl:template>
+
+<!--Type.-->
+<xsl:template match="Type">
+ <xsl:choose>
+ <xsl:when test="Type">
+ <xsl:text>sequence &lt;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>></xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ <xsl:value-of select="@type"/>
+ <xsl:if test="@nullable">
+ <xsl:text>?</xsl:text>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--Enum.-->
+<xsl:template match="Enum[descriptive]">
+ <xsl:variable name="name" select="@name"/>
+ <div class="enum" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <div class="enumvalues">
+ <h4>Values</h4>
+ <dl>
+ <xsl:apply-templates select="EnumValue"/>
+ </dl>
+ </div>
+ </div>
+</xsl:template>
+<xsl:template match="Enum[not(descriptive)]">
+</xsl:template>
+
+<!--EnumValue-->
+<xsl:template match="EnumValue">
+ <dt class="enumvalue" id="{@id}">
+ <code>
+ <xsl:value-of select="@stringvalue"/>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<xsl:template match="descriptive[not(author)]">
+ <xsl:apply-templates select="version"/>
+ <xsl:if test="author">
+ </xsl:if>
+ <xsl:apply-templates select="description"/>
+</xsl:template>
+
+<!--brief-->
+<xsl:template match="brief">
+ <div class="brief">
+ <p>
+ <xsl:apply-templates/>
+ </p>
+ </div>
+</xsl:template>
+
+<!--description in ReturnType or Argument or ScopedName-->
+<xsl:template match="Type/descriptive/description|Argument/descriptive/description|Name/descriptive/description">
+ <!--If the description contains just a single <p> then we omit
+ the <p> and just do its contents.-->
+ <xsl:choose>
+ <xsl:when test="p and count(*) = 1">
+ <xsl:apply-templates select="p/*|p/text()"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <div class="description">
+ <xsl:apply-templates/>
+ </div>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--Other description-->
+<xsl:template match="description">
+ <div class="description">
+ <xsl:apply-templates/>
+ </div>
+</xsl:template>
+
+<!--Code-->
+<xsl:template match="Code">
+ <div class="example">
+ <xsl:choose>
+ <xsl:when test="@lang">
+ <h5><xsl:value-of select="@lang"/></h5>
+ </xsl:when>
+ <xsl:otherwise>
+ <h5>Code example</h5>
+ </xsl:otherwise>
+ </xsl:choose>
+ <pre class="examplecode"><xsl:apply-templates/></pre>
+ </div>
+</xsl:template>
+
+<!--webidl : literal Web IDL from input-->
+<xsl:template match="webidl">
+ <h5>WebIDL</h5>
+ <pre class="webidl"><xsl:apply-templates/></pre>
+</xsl:template>
+
+<!--author-->
+<xsl:template match="author">
+ <li class="author"><xsl:apply-templates/></li>
+</xsl:template>
+
+<!--version-->
+<xsl:template match="version">
+ <div class="version">
+ <h2>
+ Version: <xsl:apply-templates/>
+ </h2>
+ </div>
+</xsl:template>
+
+<!--api-feature-->
+<xsl:template match="api-feature">
+ <dt>
+ <xsl:value-of select="@identifier"/>
+ </dt>
+ <dd>
+ <xsl:apply-templates/>
+ </dd>
+</xsl:template>
+
+<!--param-->
+<xsl:template match="param">
+ <li>
+ <code><xsl:value-of select="@identifier"/></code>:
+ <xsl:apply-templates/>
+ </li>
+</xsl:template>
+
+<!--def-instantiated.
+ This assumes that only one interface in the module has a def-instantiated,
+ and that interface contains just one attribute.-->
+<xsl:template match="def-instantiated">
+ <xsl:variable name="ifacename" select="../../@name"/>
+ <p>
+ <xsl:choose>
+ <xsl:when test="count(descriptive/api-feature)=1">
+ When the feature
+ </xsl:when>
+ <xsl:otherwise>
+ When any of the features
+ </xsl:otherwise>
+ </xsl:choose>
+ </p>
+ <ul>
+ <xsl:for-each select="descriptive/api-feature">
+ <li><code>
+ <xsl:value-of select="@identifier"/>
+ </code></li>
+ </xsl:for-each>
+ </ul>
+ <p>
+ is successfully requested, the interface
+ <code><xsl:apply-templates select="../../Attribute/Type"/></code>
+ is instantiated, and the resulting object appears in the global
+ namespace as
+ <code><xsl:value-of select="../../../Implements[@name2=$ifacename]/@name1"/>.<xsl:value-of select="../../Attribute/@name"/></code>.
+ </p>
+</xsl:template>
+
+
+
+<!--html elements-->
+<xsl:template match="a|b|br|dd|dl|dt|em|li|p|table|td|th|tr|ul">
+ <xsl:element name="{name()}"><xsl:for-each select="@*"><xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute></xsl:for-each><xsl:apply-templates/></xsl:element>
+</xsl:template>
+
+<xsl:template name="summary">
+ <table class="summary">
+ <thead>
+ <tr><th>Interface</th><th>Method</th></tr>
+ </thead>
+ <tbody>
+ <xsl:for-each select="Interface[descriptive]">
+ <tr><td><a href="#{@id}"><xsl:value-of select="@name"/></a></td>
+ <td>
+ <xsl:for-each select="Operation">
+
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <a href="#{concat(@name,generate-id(.))}"><xsl:value-of select="@name"/></a>
+ <xsl:text>(</xsl:text>
+ <xsl:for-each select="ArgumentList/Argument">
+ <xsl:variable name="type"><xsl:apply-templates select="Type"/></xsl:variable>
+ <xsl:value-of select="concat(normalize-space($type),' ',@name)"/>
+ <xsl:if test="position() != last()">, </xsl:if>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+ <xsl:if test="position()!=last()"><br/></xsl:if>
+ </xsl:for-each>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </tbody>
+ </table>
+</xsl:template>
+
+<!--<ref> element in literal Web IDL.-->
+<xsl:template match="ref[@ref]">
+ <a href="{@ref}">
+ <xsl:apply-templates/>
+ </a>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/Makefile b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/Makefile
new file mode 100644
index 000000000..c40939e36
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/Makefile
@@ -0,0 +1,91 @@
+########################################################################
+# $Id: Makefile 418 2010-06-16 15:26:51Z tpr $
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+UNAME = $(shell uname)
+VALIDTESTDIR = valid/idl
+VALIDTESTREFDIR = valid/xml
+VALIDTESTOBJDIR = valid/obj
+INVALIDTESTDIR = invalid/idl
+INVALIDTESTREFDIR = invalid/error
+INVALIDTESTOBJDIR = invalid/obj
+
+# The settings of SRCDIR (where to find the xsl style sheets), OBJDIR (where to
+# find widlproc and widlprocxml.dtd) and VALDTESTOBJDIR (where to put the
+# resulting XML files) reflect the directory
+# structure of the released widlproc.zip file when unzipped. ../Makefile calls
+# this Makefile with these settings overridden to reflect the directory
+# structure in svn.
+SRCDIR = ..
+OBJDIR = ..
+
+########################################################################
+# Linux configuration
+#
+ifneq (,$(filter Linux%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Darwin configuration
+#
+ifneq (,$(filter Darwin%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Windows (cygwin but using MS compiler) configuration
+#
+ifneq (,$(filter CYGWIN%, $(UNAME)))
+
+EXESUFFIX = .exe
+
+endif
+endif
+endif
+
+########################################################################
+# Common makefile
+#
+WIDLPROC = $(OBJDIR)/widlproc$(EXESUFFIX)
+DTD = $(OBJDIR)/widlprocxml.dtd
+
+VALID_WIDLS = $(patsubst $(VALIDTESTDIR)/%, %, $(wildcard $(VALIDTESTDIR)/*.widl))
+INVALID_WIDLS = $(patsubst $(INVALIDTESTDIR)/%, %, $(wildcard $(INVALIDTESTDIR)/*.widl))
+
+test : $(patsubst %.widl, $(VALIDTESTOBJDIR)/%.widlprocxml, $(VALID_WIDLS)) $(patsubst %.widl, $(INVALIDTESTOBJDIR)/%.txt, $(INVALID_WIDLS)) $(WIDLPROC)
+ @echo "$@ pass"
+
+#$(EXAMPLESOBJDIR)/%.html : $(EXAMPLESOBJDIR)/%.widlprocxml $(SRCDIR)/widlprocxmltohtml.xsl Makefile
+# cp $(SRCDIR)/widlprocxmltohtml.xsl $(dir $@)/
+# xsltproc $(dir $@)/widlprocxmltohtml.xsl $< >$@
+
+
+$(VALIDTESTOBJDIR)/%.widlprocxml : $(VALIDTESTDIR)/%.widl $(WIDLPROC) $(DTD) Makefile $(patsubst %.widl, $(VALIDTESTREFDIR)/%.widlprocxml, $(VALID_WIDLS))
+ mkdir -p $(dir $@)
+ $(WIDLPROC) $< >$@
+ cp $(OBJDIR)/widlprocxml.dtd $(dir $@)/
+ xmllint --noout --dtdvalid $(DTD) $@
+ diff $@ $(VALIDTESTREFDIR)/`basename $@`
+
+$(INVALIDTESTOBJDIR)/%.txt : $(INVALIDTESTDIR)/%.widl $(WIDLPROC) Makefile $(patsubst %.widl, $(INVALIDTESTREFDIR)/%.txt, $(INVALID_WIDLS))
+ mkdir -p $(dir $@)
+ -$(WIDLPROC) $< >$@ 2>&1
+ diff $@ $(INVALIDTESTREFDIR)/`basename $@`
+
+
+
+.DELETE_ON_ERROR:
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt
new file mode 100644
index 000000000..6f8ba8eef
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt
@@ -0,0 +1 @@
+invalid/idl/enum.widl: 1: at '1': expected string in enum
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt
new file mode 100644
index 000000000..7e504316e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt
@@ -0,0 +1 @@
+invalid/idl/module.widl: 2: at 'gfx': expected 'implements'
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt
new file mode 100644
index 000000000..eeeb25f12
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt
@@ -0,0 +1 @@
+invalid/idl/nonnullableany.widl: 2: at '?': expected identifier
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt
new file mode 100644
index 000000000..526622599
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt
@@ -0,0 +1 @@
+invalid/idl/nonnullableobjects.widl: 4: at '?': expected identifier
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt
new file mode 100644
index 000000000..5646608cd
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt
@@ -0,0 +1 @@
+invalid/idl/scopedname.widl: 2: at ':': expected identifier
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt
new file mode 100644
index 000000000..15960cb8b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt
@@ -0,0 +1 @@
+invalid/idl/sequenceAsAttribute.widl: 2: at 'sequence': expected type
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl
new file mode 100644
index 000000000..155a892c5
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl
@@ -0,0 +1 @@
+invalid/idl/stringconstants.idl: 2: at 'DOMString': expected acceptable constant type
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl
new file mode 100644
index 000000000..c355c3251
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl
@@ -0,0 +1 @@
+enum foo { 1, 2, 3}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl
new file mode 100644
index 000000000..a4c79fdf1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl
@@ -0,0 +1,25 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+module gfx {
+
+ module geom {
+ interface Shape { /* ... */ };
+ interface Rectangle : Shape { /* ... */ };
+ interface Path : Shape { /* ... */ };
+ };
+
+ interface GraphicsContext {
+ void fillShape(geom::Shape s);
+ void strokeShape(geom::Shape s);
+ };
+};
+
+module gui {
+
+ interface Widget { /* ... */ };
+
+ interface Window : Widget {
+ gfx::GraphicsContext getGraphicsContext();
+ };
+
+ interface Button : Widget { /* ... */ };
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl
new file mode 100644
index 000000000..389576555
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl
@@ -0,0 +1,3 @@
+interface NonNullable {
+ attribute any? foo;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl
new file mode 100644
index 000000000..1deac5aee
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl
@@ -0,0 +1,5 @@
+interface Foo {};
+
+interface NonNullable {
+ attribute Foo?? foo;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl
new file mode 100644
index 000000000..ff65522f2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl
@@ -0,0 +1,18 @@
+// getraises and setraises are not longer valid Web IDL
+interface Person {
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ attribute DOMString name setraises (InvalidName);
+
+ // An attribute whose value cannot be assigned to, and which can raise an
+ // exception some circumstances.
+ readonly attribute DOMString petName getraises (NoSuchPet);
+};
+
+exception SomeException {
+};
+
+interface ExceptionThrower {
+ // This attribute always throws a SomeException and never returns a value.
+ attribute long valueOf getraises(SomeException);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl
new file mode 100644
index 000000000..cfcb1ccc9
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl
@@ -0,0 +1,2 @@
+// scoped names are no longer valid in WebIDL
+ typedef gfx::geom::geom2d::Point Point;
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl
new file mode 100644
index 000000000..c23da82ac
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl
@@ -0,0 +1,3 @@
+interface sequenceAsAttribute {
+ attribute sequence<short> invalid;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl
new file mode 100644
index 000000000..bdfbfa709
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// omittable is no longer a recognized keywoard as of 20110905
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl
new file mode 100644
index 000000000..44fd3ff13
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl
@@ -0,0 +1,3 @@
+interface Util {
+ const DOMString hello = "world";
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl
new file mode 100644
index 000000000..2343bb963
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface B {
+ void g();
+ void g(B b);
+ void g([AllowAny] DOMString s);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl
new file mode 100644
index 000000000..22e21fb65
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl
new file mode 100644
index 000000000..7e1d691cb
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ // A simple attribute that can be set to any value the range an unsigned
+ // short can take.
+ attribute unsigned short age;
+
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl
new file mode 100644
index 000000000..d92f6a18c
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl
@@ -0,0 +1,5 @@
+callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl
new file mode 100644
index 000000000..92acb1c01
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface NumberQuadrupler {
+ // This operation simply returns four times the given number x.
+ legacycaller float compute(float x);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl
new file mode 100644
index 000000000..5e28ae9c1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl
new file mode 100644
index 000000000..f93ec08a6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl
new file mode 100644
index 000000000..48f8a0fdc
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl
@@ -0,0 +1,9 @@
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+dictionary WetPaintOptions : PaintOptions {
+ float hydrometry;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl
new file mode 100644
index 000000000..f46b7ba78
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl
@@ -0,0 +1,11 @@
+// Extracted from Web IDL editors draft May 31 2011
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl
new file mode 100644
index 000000000..fb801101f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl
@@ -0,0 +1,33 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl
new file mode 100644
index 000000000..003e9226f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl
@@ -0,0 +1,34 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+* <p><img src="foo.png" alt="Valid"/></p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl
new file mode 100644
index 000000000..851fca2e6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl
@@ -0,0 +1,8 @@
+enum MealType { "rice", "noodles", "other" };
+
+interface Meal {
+ attribute MealType type;
+ attribute float size; // in grams
+
+ void initialize(MealType type, float size);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl
new file mode 100644
index 000000000..6b3e0eda2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl
new file mode 100644
index 000000000..258fdeba6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl
@@ -0,0 +1,7 @@
+// from http://lists.w3.org/Archives/Public/public-script-coord/2010OctDec/0112.html
+ exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : DOMException { };
+ exception NoModificationAllowedError : DOMException { }; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl
new file mode 100644
index 000000000..f4b6ae29e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};
+
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl
new file mode 100644
index 000000000..bdf87e1c7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl
new file mode 100644
index 000000000..33893d4c6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl
@@ -0,0 +1,44 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ // Typedef identifier: "number"
+ // Qualified name: "::framework::number"
+ typedef float number;
+
+ // Exception identifier: "FrameworkException"
+ // Qualified name: "::framework::FrameworkException"
+ exception FrameworkException {
+
+ // Constant identifier: "ERR_NOT_FOUND"
+ // Qualified name: "::framework::FrameworkException::ERR_NOT_FOUND"
+ const long ERR_NOT_FOUND = 1;
+
+ // Exception field identifier: "code"
+ long code;
+ };
+
+ // Interface identifier: "System"
+ // Qualified name: "::framework::System"
+ interface System {
+
+ // Operation identifier: "createObject"
+ // Operation argument identifier: "interface"
+ object createObject(DOMString _interface);
+
+ // Operation has no identifier; it declares a getter.
+ getter DOMString (DOMString keyName);
+ };
+
+
+ // Interface identifier: "TextField"
+ // Qualified name: "::framework::gui::TextField"
+ interface TextField {
+
+ // Attribute identifier: "const"
+ attribute boolean _const;
+
+ // Attribute identifier: "value"
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl
new file mode 100644
index 000000000..7a310926f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Node {
+ readonly attribute unsigned short nodeType;
+ // ...
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ EventListener listener,
+ boolean useCapture);
+ // ...
+ };
+
+ Node implements EventTarget;
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl
new file mode 100644
index 000000000..acf0ed3bf
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl
new file mode 100644
index 000000000..558e81164
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl
@@ -0,0 +1,16 @@
+interface Animal {
+
+ // A simple attribute that can be set to any string value.
+ readonly attribute DOMString name;
+};
+
+interface Person : Animal {
+
+ // An attribute whose value cannot be assigned to.
+ readonly attribute unsigned short age;
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ // Its getter behavior is inherited from Animal, and need not be specified
+ // the description of Person.
+ inherit attribute DOMString name;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl
new file mode 100644
index 000000000..7921def77
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : Animal {
+ attribute Dog pet;
+};
+
+interface Dog : Animal {
+ attribute Human owner;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl
new file mode 100644
index 000000000..3bf1b36de
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl
@@ -0,0 +1,35 @@
+interface SessionManager {
+ Session getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionManager2 {
+ Session2 getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session2 iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ Node iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ Node iterator object;
+ }; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl
new file mode 100644
index 000000000..c468b78f8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : HTMLMediaElement {
+ // ...
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl
new file mode 100644
index 000000000..c17d75ff8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl
new file mode 100644
index 000000000..ccbf625ff
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+ // ...
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl
new file mode 100644
index 000000000..83d1d40b2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl
@@ -0,0 +1,13 @@
+// Extracted from WebIDL spec 2011-05-23
+
+interface A {
+ // ...
+};
+interface B {
+ // ...
+};
+interface C {
+ void f(A? x);
+ void f(B? x);
+
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl
new file mode 100644
index 000000000..379053b45
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl
@@ -0,0 +1,4 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl
new file mode 100644
index 000000000..ef1288a88
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl
@@ -0,0 +1,20 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ // ...
+};
+
+interface B {
+ // ...
+};
+
+interface C {
+ void f(A x);
+ void f(B x);
+};
+
+interface A {
+ /* f1 */ void f(DOMString a);
+ /* f2 */ void f([AllowAny] DOMString a, DOMString b, float... c);
+ /* f3 */ void f();
+ /* f4 */ void f(long a, DOMString b, optional DOMString c, float... d);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl
new file mode 100644
index 000000000..79211c29e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl
new file mode 100644
index 000000000..90e7e0ea4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl
@@ -0,0 +1,7 @@
+interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl
new file mode 100644
index 000000000..92939601a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl
@@ -0,0 +1,19 @@
+interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl
new file mode 100644
index 000000000..30dd5cbca
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl
new file mode 100644
index 000000000..1e50a4ee3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Person {
+ [PutForwards=full] readonly attribute Name name;
+ attribute unsigned short age;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl
new file mode 100644
index 000000000..13997cb1d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl
@@ -0,0 +1,17 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ // An operation that takes no arguments, returns a boolean
+ boolean isMouseOver();
+
+ // Overloaded operations.
+ void setDimensions(Dimensions size);
+ void setDimensions(unsigned long width, unsigned long height);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl
new file mode 100644
index 000000000..c14d0c376
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl
new file mode 100644
index 000000000..a1aa931f5
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// edited to remove sequence as attributes, now invalid
+interface Canvas {
+ void drawPolygon(sequence<float> coordinates);
+ sequence<float> getInflectionPoints();
+ // ...
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl
new file mode 100644
index 000000000..6f6ccd0e8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl
@@ -0,0 +1,64 @@
+interface Transaction {
+ readonly attribute Account from;
+ readonly attribute Account to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute Account2 from;
+ readonly attribute Account2 to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl
new file mode 100644
index 000000000..5b2cd3659
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl
@@ -0,0 +1,11 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Point { /* ... */ };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static Point triangulate(Circle c1, Circle c2, Circle c3);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl
new file mode 100644
index 000000000..c964ecb93
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl
new file mode 100644
index 000000000..b5d7c87e7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl
new file mode 100644
index 000000000..4eb483d9b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl
new file mode 100644
index 000000000..d3c55b008
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl
new file mode 100644
index 000000000..e30050f84
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl
new file mode 100644
index 000000000..b4c17d8d3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl
@@ -0,0 +1,22 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence<Point> PointSequence;
+
+ interface Rect {
+ attribute Point topleft;
+ attribute Point bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute Rect bounds;
+
+ boolean pointWithinBounds(Point p);
+ boolean allPointsWithinBounds(PointSequence ps);
+ };
+
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl
new file mode 100644
index 000000000..95e31c169
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl
@@ -0,0 +1,3 @@
+interface Suffixes {
+ void test(sequence<DOMString[]?>? foo);
+};
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl
new file mode 100644
index 000000000..4d99f0196
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl
@@ -0,0 +1,3 @@
+interface Union {
+ attribute (float or (Date or Event) or (Node or DOMString)?) test;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl
new file mode 100644
index 000000000..51fae4cc1
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml
new file mode 100644
index 000000000..7da508bcb
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface B {
+ void g();
+ void g(<ref>B</ref> b);
+ void g([AllowAny] DOMString s);
+};</webidl>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+ void g();
+ void g(<ref>B</ref> b);
+ void g([AllowAny] DOMString s);
+};</webidl>
+ <Operation name="g" id="::B::g">
+ <webidl> void g();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="g" id="::B::g">
+ <webidl> void g(<ref>B</ref> b);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="b">
+ <Type name="B"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="g" id="::B::g">
+ <webidl> void g([AllowAny] DOMString s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="AllowAny">
+ <webidl>AllowAny</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml
new file mode 100644
index 000000000..3df72ff16
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+};</webidl>
+ <Interface name="LotteryResults" id="::LotteryResults">
+ <webidl>[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="numbers" id="::LotteryResults::numbers">
+ <webidl> readonly attribute unsigned short[][] numbers;</webidl>
+ <Type type="array">
+ <Type type="array">
+ <Type type="unsigned short"/>
+ </Type>
+ </Type>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml
new file mode 100644
index 000000000..89bd8ac9b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ attribute unsigned short age;
+
+};</webidl>
+ <Exception name="InvalidName" id="::InvalidName">
+ <webidl>exception InvalidName {
+ DOMString reason;
+};</webidl>
+ <ExceptionField name="reason" id="::InvalidName::reason">
+ <webidl> DOMString reason;</webidl>
+ <Type type="DOMString"/>
+ </ExceptionField>
+ </Exception>
+ <Exception name="NoSuchPet" id="::NoSuchPet">
+ <webidl>exception NoSuchPet { };</webidl>
+ </Exception>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person {
+
+ attribute unsigned short age;
+
+};</webidl>
+ <Attribute name="age" id="::Person::age">
+ <webidl> attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml
new file mode 100644
index 000000000..9eac06ce2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+};</webidl>
+ <Callback name="AsyncOperationCallback" id="::AsyncOperationCallback">
+ <webidl>callback AsyncOperationCallback = void (DOMString status);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="status">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Callback>
+ <Interface name="EventHandler" callback="callback" id="::EventHandler">
+ <webidl>callback interface EventHandler {
+ void eventOccurred(DOMString details);
+};</webidl>
+ <Operation name="eventOccurred" id="::EventHandler::eventOccurred">
+ <webidl> void eventOccurred(DOMString details);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="details">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml
new file mode 100644
index 000000000..9754d4e02
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface NumberQuadrupler {
+ legacycaller float compute(float x);
+};</webidl>
+ <Interface name="NumberQuadrupler" id="::NumberQuadrupler">
+ <webidl>interface NumberQuadrupler {
+ legacycaller float compute(float x);
+};</webidl>
+ <Operation legacycaller="legacycaller" name="compute" id="::NumberQuadrupler::compute">
+ <webidl> legacycaller float compute(float x);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml
new file mode 100644
index 000000000..51cb4331f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+};</webidl>
+ <Interface name="Util" id="::Util">
+ <webidl>interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};</webidl>
+ <Const name="DEBUG" value="false" id="::Util::DEBUG">
+ <webidl> const boolean DEBUG = false;</webidl>
+ <Type type="boolean"/>
+ </Const>
+ <Const name="negative" value="-1" id="::Util::negative">
+ <webidl> const short negative = -1;</webidl>
+ <Type type="short"/>
+ </Const>
+ <Const name="LF" value="10" id="::Util::LF">
+ <webidl> const octet LF = 10;</webidl>
+ <Type type="octet"/>
+ </Const>
+ <Const name="BIT_MASK" value="0x0000fc00" id="::Util::BIT_MASK">
+ <webidl> const unsigned long BIT_MASK = 0x0000fc00;</webidl>
+ <Type type="unsigned long"/>
+ </Const>
+ <Const name="AVOGADRO" value="6.022e23" id="::Util::AVOGADRO">
+ <webidl> const float AVOGADRO = 6.022e23;</webidl>
+ <Type type="float"/>
+ </Const>
+ <Const name="sobig" value="Infinity" id="::Util::sobig">
+ <webidl> const unrestricted float sobig = Infinity;</webidl>
+ <Type type="unrestricted float"/>
+ </Const>
+ <Const name="minusonedividedbyzero" value="-Infinity" id="::Util::minusonedividedbyzero">
+ <webidl> const unrestricted double minusonedividedbyzero = -Infinity;</webidl>
+ <Type type="unrestricted double"/>
+ </Const>
+ <Const name="notanumber" value="NaN" id="::Util::notanumber">
+ <webidl> const short notanumber = NaN;</webidl>
+ <Type type="short"/>
+ </Const>
+ </Interface>
+ <Exception name="Error" id="::Error">
+ <webidl>exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+};</webidl>
+ <Const name="ERR_UNKNOWN" value="0" id="::Error::ERR_UNKNOWN">
+ <webidl> const short ERR_UNKNOWN = 0;</webidl>
+ <Type type="short"/>
+ </Const>
+ <Const name="ERR_OUT_OF_MEMORY" value="1" id="::Error::ERR_OUT_OF_MEMORY">
+ <webidl> const short ERR_OUT_OF_MEMORY = 1;</webidl>
+ <Type type="short"/>
+ </Const>
+ <ExceptionField name="errorCode" id="::Error::errorCode">
+ <webidl> short errorCode;</webidl>
+ <Type type="short"/>
+ </ExceptionField>
+ </Exception>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml
new file mode 100644
index 000000000..8e78fbab3
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+};</webidl>
+ <Interface name="Circle" id="::Circle">
+ <webidl>[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ <ExtendedAttribute name="Constructor">
+ <webidl> Constructor(float radius)</webidl>
+ <ArgumentList>
+ <Argument name="radius">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="r" id="::Circle::r">
+ <webidl> attribute float r;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cx" id="::Circle::cx">
+ <webidl> attribute float cx;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cy" id="::Circle::cy">
+ <webidl> attribute float cy;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="circumference" id="::Circle::circumference">
+ <webidl> readonly attribute float circumference;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml
new file mode 100644
index 000000000..269a83cd8
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};
+
+dictionary WetPaintOptions : <ref>PaintOptions</ref> {
+ float hydrometry;
+};</webidl>
+ <Dictionary name="PaintOptions" id="::PaintOptions">
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};</webidl>
+ <DictionaryMember name="fillPattern" stringvalue="black" id="::PaintOptions::fillPattern">
+ <webidl> DOMString? fillPattern = &quot;black&quot;;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="strokePattern" value="null" id="::PaintOptions::strokePattern">
+ <webidl> DOMString? strokePattern = null;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="position" id="::PaintOptions::position">
+ <webidl> <ref>Point</ref> position;</webidl>
+ <Type name="Point"/>
+ </DictionaryMember>
+ </Dictionary>
+ <Dictionary name="WetPaintOptions" id="::WetPaintOptions">
+ <webidl>dictionary WetPaintOptions : <ref>PaintOptions</ref> {
+ float hydrometry;
+};</webidl>
+ <DictionaryInheritance>
+ <Name name="PaintOptions"/>
+ </DictionaryInheritance>
+ <DictionaryMember name="hydrometry" id="::WetPaintOptions::hydrometry">
+ <webidl> float hydrometry;</webidl>
+ <Type type="float"/>
+ </DictionaryMember>
+ </Dictionary>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml
new file mode 100644
index 000000000..978ccb4e2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+};</webidl>
+ <Dictionary name="PaintOptions" id="::PaintOptions">
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};</webidl>
+ <DictionaryMember name="fillPattern" stringvalue="black" id="::PaintOptions::fillPattern">
+ <webidl> DOMString? fillPattern = &quot;black&quot;;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="strokePattern" value="null" id="::PaintOptions::strokePattern">
+ <webidl> DOMString? strokePattern = null;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="position" id="::PaintOptions::position">
+ <webidl> <ref>Point</ref> position;</webidl>
+ <Type name="Point"/>
+ </DictionaryMember>
+ </Dictionary>
+ <Dictionary name="A" partial="partial" id="::A">
+ <webidl>partial dictionary A {
+ long h;
+ long d;
+};</webidl>
+ <DictionaryMember name="h" id="::A::h">
+ <webidl> long h;</webidl>
+ <Type type="long"/>
+ </DictionaryMember>
+ <DictionaryMember name="d" id="::A::d">
+ <webidl> long d;</webidl>
+ <Type type="long"/>
+ </DictionaryMember>
+ </Dictionary>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml
new file mode 100644
index 000000000..1611f0e57
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Documentation {};</webidl>
+ <Interface name="Documentation" id="::Documentation">
+ <webidl>interface Documentation {};</webidl>
+ <descriptive>
+ <brief>
+ Testing documentation features
+ </brief>
+ <description>
+ <p>
+This is a
+single paragraph
+ </p>
+ <p>
+This is valid. </p>
+ <p>
+This is <em>valid</em>. </p>
+ <p>
+This is <b>valid</b>. </p>
+ <p>
+This is <a href=''>valid</a>. </p>
+ <ul>
+ <li>
+This </li>
+ <li>
+is </li>
+ <li>
+valid </li>
+ </ul>
+ <dl>
+ <dt>
+This </dt>
+ <dd>
+valid </dd>
+ </dl>
+ <table>
+ <tr>
+ <td>
+this </td>
+ <td>
+is </td>
+ </tr>
+ <tr>
+ <td>
+valid </td>
+ </tr>
+ </table>
+ <p>
+This is <br/> valid. </p>
+ <p>
+This is <br /> valid. </p>
+ <p>
+This is <br/> valid. </p>
+ </description>
+ </descriptive>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml
new file mode 100644
index 000000000..afe4527c2
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Documentation {};</webidl>
+ <Interface name="Documentation" id="::Documentation">
+ <webidl>interface Documentation {};</webidl>
+ <descriptive>
+ <brief>
+ Testing documentation features
+ </brief>
+ <description>
+ <p>
+This is a
+single paragraph
+ </p>
+ <p>
+This is valid. </p>
+ <p>
+This is <em>valid</em>. </p>
+ <p>
+This is <b>valid</b>. </p>
+ <p>
+This is <a href=''>valid</a>. </p>
+ <ul>
+ <li>
+This </li>
+ <li>
+is </li>
+ <li>
+valid </li>
+ </ul>
+ <dl>
+ <dt>
+This </dt>
+ <dd>
+valid </dd>
+ </dl>
+ <table>
+ <tr>
+ <td>
+this </td>
+ <td>
+is </td>
+ </tr>
+ <tr>
+ <td>
+valid </td>
+ </tr>
+ </table>
+ <p>
+This is <br/> valid. </p>
+ <p>
+This is <br /> valid. </p>
+ <p>
+This is <br/> valid. </p>
+ <p>
+<img src="foo.png" alt="Valid"/> </p>
+ </description>
+ </descriptive>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml
new file mode 100644
index 000000000..e1e8258fb
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>enum MealType { &quot;rice&quot;, &quot;noodles&quot;, &quot;other&quot; };
+
+interface Meal {
+ attribute <ref>MealType</ref> type;
+ attribute float size;
+
+ void initialize(<ref>MealType</ref> type, float size);
+};</webidl>
+ <Enum name="MealType" id="::MealType">
+ <webidl>enum MealType { &quot;rice&quot;, &quot;noodles&quot;, &quot;other&quot; };</webidl>
+ <EnumValue stringvalue="rice">
+ <webidl> &quot;rice</webidl>
+ </EnumValue>
+ <EnumValue stringvalue="noodles">
+ <webidl> &quot;noodles</webidl>
+ </EnumValue>
+ <EnumValue stringvalue="other">
+ <webidl> &quot;other</webidl>
+ </EnumValue>
+ </Enum>
+ <Interface name="Meal" id="::Meal">
+ <webidl>interface Meal {
+ attribute <ref>MealType</ref> type;
+ attribute float size;
+
+ void initialize(<ref>MealType</ref> type, float size);
+};</webidl>
+ <Attribute name="type" id="::Meal::type">
+ <webidl> attribute <ref>MealType</ref> type;</webidl>
+ <Type name="MealType"/>
+ </Attribute>
+ <Attribute name="size" id="::Meal::size">
+ <webidl> attribute float size;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Operation name="initialize" id="::Meal::initialize">
+ <webidl> void initialize(<ref>MealType</ref> type, float size);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="type">
+ <Type name="MealType"/>
+ </Argument>
+ <Argument name="size">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml
new file mode 100644
index 000000000..c322d0a5e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="getProperty" id="::Dictionary::getProperty">
+ <webidl> getter float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" name="setProperty" id="::Dictionary::setProperty">
+ <webidl> setter void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="getProperty" id="::Dictionary::getProperty">
+ <webidl> float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="setProperty" id="::Dictionary::setProperty">
+ <webidl> void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter">
+ <webidl> getter float (DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter">
+ <webidl> setter void (DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml
new file mode 100644
index 000000000..3a1f868a4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : <ref>DOMException</ref> { };
+ exception NoModificationAllowedError : <ref>DOMException</ref> { };</webidl>
+ <Exception name="DOMException" id="::DOMException">
+ <webidl> exception DOMException {
+ unsigned short code;
+ };</webidl>
+ <ExceptionField name="code" id="::DOMException::code">
+ <webidl> unsigned short code;</webidl>
+ <Type type="unsigned short"/>
+ </ExceptionField>
+ </Exception>
+ <Exception name="HierarchyRequestError" id="::HierarchyRequestError">
+ <webidl> exception HierarchyRequestError : <ref>DOMException</ref> { };</webidl>
+ <ExceptionInheritance>
+ <Name name="DOMException"/>
+ </ExceptionInheritance>
+ </Exception>
+ <Exception name="NoModificationAllowedError" id="::NoModificationAllowedError">
+ <webidl> exception NoModificationAllowedError : <ref>DOMException</ref> { };</webidl>
+ <ExceptionInheritance>
+ <Name name="DOMException"/>
+ </ExceptionInheritance>
+ </Exception>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml
new file mode 100644
index 000000000..ac93320fe
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};</webidl>
+ <Interface name="Dahut" id="::Dahut">
+ <webidl>interface Dahut {
+ attribute DOMString type;
+};</webidl>
+ <Attribute name="type" id="::Dahut::type">
+ <webidl> attribute DOMString type;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Exception name="SomeException" id="::SomeException">
+ <webidl>exception SomeException {
+};</webidl>
+ </Exception>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml
new file mode 100644
index 000000000..76afc058c
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter">
+ <webidl> getter float (DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter">
+ <webidl> setter void (DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml
new file mode 100644
index 000000000..b6024e5ff
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> typedef float number;
+
+ exception FrameworkException {
+
+ const long ERR_NOT_FOUND = 1;
+
+ long code;
+ };
+
+ interface System {
+
+ object createObject(DOMString _interface);
+
+ getter DOMString (DOMString keyName);
+ };
+
+
+ interface TextField {
+
+ attribute boolean _const;
+
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+};</webidl>
+ <Typedef name="number" id="::number">
+ <webidl> typedef float number;</webidl>
+ <Type type="float"/>
+ </Typedef>
+ <Exception name="FrameworkException" id="::FrameworkException">
+ <webidl> exception FrameworkException {
+
+ const long ERR_NOT_FOUND = 1;
+
+ long code;
+ };</webidl>
+ <Const name="ERR_NOT_FOUND" value="1" id="::FrameworkException::ERR_NOT_FOUND">
+ <webidl> const long ERR_NOT_FOUND = 1;</webidl>
+ <Type type="long"/>
+ </Const>
+ <ExceptionField name="code" id="::FrameworkException::code">
+ <webidl> long code;</webidl>
+ <Type type="long"/>
+ </ExceptionField>
+ </Exception>
+ <Interface name="System" id="::System">
+ <webidl> interface System {
+
+ object createObject(DOMString _interface);
+
+ getter DOMString (DOMString keyName);
+ };</webidl>
+ <Operation name="createObject" id="::System::createObject">
+ <webidl> object createObject(DOMString _interface);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="_interface">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter">
+ <webidl> getter DOMString (DOMString keyName);</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList>
+ <Argument name="keyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="TextField" id="::TextField">
+ <webidl> interface TextField {
+
+ attribute boolean _const;
+
+ attribute DOMString? _value;
+ };</webidl>
+ <Attribute name="_const" id="::TextField::_const">
+ <webidl> attribute boolean _const;</webidl>
+ <Type type="boolean"/>
+ </Attribute>
+ <Attribute name="_value" id="::TextField::_value">
+ <webidl> attribute DOMString? _value;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Foo" id="::Foo">
+ <webidl>interface Foo {
+ void op(object interface);
+};</webidl>
+ <Operation name="op" id="::Foo::op">
+ <webidl> void op(object interface);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="interface">
+ <Type type="object"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml
new file mode 100644
index 000000000..3d1c1ab84
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> interface Node {
+ readonly attribute unsigned short nodeType;
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);
+ };
+
+ <ref>Node</ref> implements <ref>EventTarget</ref>;</webidl>
+ <Interface name="Node" id="::Node">
+ <webidl> interface Node {
+ readonly attribute unsigned short nodeType;
+ };</webidl>
+ <Attribute readonly="readonly" name="nodeType" id="::Node::nodeType">
+ <webidl> readonly attribute unsigned short nodeType;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+ <Interface name="EventTarget" id="::EventTarget">
+ <webidl> interface EventTarget {
+ void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);
+ };</webidl>
+ <Operation name="addEventListener" id="::EventTarget::addEventListener">
+ <webidl> void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="type">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="listener">
+ <Type name="EventListener"/>
+ </Argument>
+ <Argument name="useCapture">
+ <Type type="boolean"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Implements name1="Node" name2="EventTarget">
+ <webidl> <ref>Node</ref> implements <ref>EventTarget</ref>;</webidl>
+ </Implements>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml
new file mode 100644
index 000000000..fb83621b6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+};</webidl>
+ <Interface name="OrderedMap" id="::OrderedMap">
+ <webidl>interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+};</webidl>
+ <Attribute readonly="readonly" name="size" id="::OrderedMap::size">
+ <webidl> readonly attribute unsigned long size;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="getByIndex" id="::OrderedMap::getByIndex">
+ <webidl> getter any getByIndex(unsigned long index);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" name="setByIndex" id="::OrderedMap::setByIndex">
+ <webidl> setter void setByIndex(unsigned long index, any value);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ <Argument name="value">
+ <Type type="any"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation deleter="deleter" name="removeByIndex" id="::OrderedMap::removeByIndex">
+ <webidl> deleter void removeByIndex(unsigned long index);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter" name="get" id="::OrderedMap::get">
+ <webidl> getter any get(DOMString name);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" creator="creator" name="set" id="::OrderedMap::set">
+ <webidl> setter creator void set(DOMString name, any value);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="value">
+ <Type type="any"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation deleter="deleter" name="remove" id="::OrderedMap::remove">
+ <webidl> deleter void remove(DOMString name);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml
new file mode 100644
index 000000000..55e7a317f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Animal {
+
+ readonly attribute DOMString name;
+};
+
+interface Person : <ref>Animal</ref> {
+
+ readonly attribute unsigned short age;
+
+ inherit attribute DOMString name;
+};</webidl>
+ <Interface name="Animal" id="::Animal">
+ <webidl>interface Animal {
+
+ readonly attribute DOMString name;
+};</webidl>
+ <Attribute readonly="readonly" name="name" id="::Animal::name">
+ <webidl> readonly attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person : <ref>Animal</ref> {
+
+ readonly attribute unsigned short age;
+
+ inherit attribute DOMString name;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute readonly="readonly" name="age" id="::Person::age">
+ <webidl> readonly attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ <Attribute inherit="inherit" name="name" id="::Person::name">
+ <webidl> inherit attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml
new file mode 100644
index 000000000..94f0e29df
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : <ref>Animal</ref> {
+ attribute <ref>Dog</ref> pet;
+};
+
+interface Dog : <ref>Animal</ref> {
+ attribute <ref>Human</ref> owner;
+};</webidl>
+ <Interface name="Animal" id="::Animal">
+ <webidl>interface Animal {
+ attribute DOMString name;
+};</webidl>
+ <Attribute name="name" id="::Animal::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Human" id="::Human">
+ <webidl>interface Human : <ref>Animal</ref> {
+ attribute <ref>Dog</ref> pet;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute name="pet" id="::Human::pet">
+ <webidl> attribute <ref>Dog</ref> pet;</webidl>
+ <Type name="Dog"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Dog" id="::Dog">
+ <webidl>interface Dog : <ref>Animal</ref> {
+ attribute <ref>Human</ref> owner;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute name="owner" id="::Dog::owner">
+ <webidl> attribute <ref>Human</ref> owner;</webidl>
+ <Type name="Human"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml
new file mode 100644
index 000000000..8ca95fbbd
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface SessionManager {
+ <ref>Session</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session</ref> iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+};
+
+interface SessionManager2 {
+ <ref>Session2</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session2</ref> iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ <ref>Node</ref> iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ <ref>Node</ref> iterator object;
+ };</webidl>
+ <Interface name="SessionManager" id="::SessionManager">
+ <webidl>interface SessionManager {
+ <ref>Session</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session</ref> iterator;
+};</webidl>
+ <Operation name="getSessionForUser" id="::SessionManager::getSessionForUser">
+ <webidl> <ref>Session</ref> getSessionForUser(DOMString username);</webidl>
+ <Type name="Session"/>
+ <ArgumentList>
+ <Argument name="username">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Attribute readonly="readonly" name="sessionCount" id="::SessionManager::sessionCount">
+ <webidl> readonly attribute unsigned long sessionCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Iterator>
+ <webidl> <ref>Session</ref> iterator;</webidl>
+ <Type name="Session"/>
+ </Iterator>
+ </Interface>
+ <Interface name="Session" id="::Session">
+ <webidl>interface Session {
+ readonly attribute DOMString username;
+};</webidl>
+ <Attribute readonly="readonly" name="username" id="::Session::username">
+ <webidl> readonly attribute DOMString username;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="SessionManager2" id="::SessionManager2">
+ <webidl>interface SessionManager2 {
+ <ref>Session2</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session2</ref> iterator = SessionIterator;
+};</webidl>
+ <Operation name="getSessionForUser" id="::SessionManager2::getSessionForUser">
+ <webidl> <ref>Session2</ref> getSessionForUser(DOMString username);</webidl>
+ <Type name="Session2"/>
+ <ArgumentList>
+ <Argument name="username">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Attribute readonly="readonly" name="sessionCount" id="::SessionManager2::sessionCount">
+ <webidl> readonly attribute unsigned long sessionCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Iterator interface="SessionIterator">
+ <webidl> <ref>Session2</ref> iterator = SessionIterator;</webidl>
+ <Type name="Session2"/>
+ </Iterator>
+ </Interface>
+ <Interface name="Session2" id="::Session2">
+ <webidl>interface Session2 {
+ readonly attribute DOMString username;
+};</webidl>
+ <Attribute readonly="readonly" name="username" id="::Session2::username">
+ <webidl> readonly attribute DOMString username;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="SessionIterator" id="::SessionIterator">
+ <webidl>interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};</webidl>
+ <Attribute readonly="readonly" name="remainingSessions" id="::SessionIterator::remainingSessions">
+ <webidl> readonly attribute unsigned long remainingSessions;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ </Interface>
+ <Interface name="NodeList" id="::NodeList">
+ <webidl> interface NodeList {
+ <ref>Node</ref> iterator = NodeIterator;
+ };</webidl>
+ <Iterator interface="NodeIterator">
+ <webidl> <ref>Node</ref> iterator = NodeIterator;</webidl>
+ <Type name="Node"/>
+ </Iterator>
+ </Interface>
+ <Interface name="NodeIterator" id="::NodeIterator">
+ <webidl> interface NodeIterator {
+ <ref>Node</ref> iterator object;
+ };</webidl>
+ <IteratorObject>
+ <webidl> <ref>Node</ref> iterator object;</webidl>
+ <Type name="Node"/>
+ </IteratorObject>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml
new file mode 100644
index 000000000..b575b8705
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Module name="gfx" id="::gfx">
+ <webidl>module gfx {
+
+ module geom {
+ interface Shape { };
+ interface Rectangle : <ref>Shape</ref> { };
+ interface Path : <ref>Shape</ref> { };
+ };
+
+ interface GraphicsContext {
+ void fillShape(<ref>geom::Shape</ref> s);
+ void strokeShape(<ref>geom::Shape</ref> s);
+ };
+};</webidl>
+ <Module name="geom" id="::gfx::geom">
+ <webidl> module geom {
+ interface Shape { };
+ interface Rectangle : <ref>Shape</ref> { };
+ interface Path : <ref>Shape</ref> { };
+ };</webidl>
+ <Interface name="Shape" id="::gfx::geom::Shape">
+ <webidl> interface Shape { };</webidl>
+ </Interface>
+ <Interface name="Rectangle" id="::gfx::geom::Rectangle">
+ <webidl> interface Rectangle : <ref>Shape</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Shape"/>
+ </InterfaceInheritance>
+ </Interface>
+ <Interface name="Path" id="::gfx::geom::Path">
+ <webidl> interface Path : <ref>Shape</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Shape"/>
+ </InterfaceInheritance>
+ </Interface>
+ </Module>
+ <Interface name="GraphicsContext" id="::gfx::GraphicsContext">
+ <webidl> interface GraphicsContext {
+ void fillShape(<ref>geom::Shape</ref> s);
+ void strokeShape(<ref>geom::Shape</ref> s);
+ };</webidl>
+ <Operation name="fillShape" id="::gfx::GraphicsContext::fillShape">
+ <webidl> void fillShape(<ref>geom::Shape</ref> s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <Type name="geom::Shape"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="strokeShape" id="::gfx::GraphicsContext::strokeShape">
+ <webidl> void strokeShape(<ref>geom::Shape</ref> s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <Type name="geom::Shape"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ </Module>
+ <Module name="gui" id="::gui">
+ <webidl>module gui {
+
+ interface Widget { };
+
+ interface Window : <ref>Widget</ref> {
+ <ref>gfx::GraphicsContext</ref> getGraphicsContext();
+ };
+
+ interface Button : <ref>Widget</ref> { };
+};</webidl>
+ <Interface name="Widget" id="::gui::Widget">
+ <webidl> interface Widget { };</webidl>
+ </Interface>
+ <Interface name="Window" id="::gui::Window">
+ <webidl> interface Window : <ref>Widget</ref> {
+ <ref>gfx::GraphicsContext</ref> getGraphicsContext();
+ };</webidl>
+ <InterfaceInheritance>
+ <Name name="Widget"/>
+ </InterfaceInheritance>
+ <Operation name="getGraphicsContext" id="::gui::Window::getGraphicsContext">
+ <webidl> <ref>gfx::GraphicsContext</ref> getGraphicsContext();</webidl>
+ <Type name="gfx::GraphicsContext"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="Button" id="::gui::Button">
+ <webidl> interface Button : <ref>Widget</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Widget"/>
+ </InterfaceInheritance>
+ </Interface>
+ </Module>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml
new file mode 100644
index 000000000..9f6616128
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : <ref>HTMLMediaElement</ref> {
+};</webidl>
+ <Interface name="HTMLAudioElement" id="::HTMLAudioElement">
+ <webidl>[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : <ref>HTMLMediaElement</ref> {
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NamedConstructor" value="Audio">
+ <webidl>NamedConstructor</webidl>
+ </ExtendedAttribute>
+ <ExtendedAttribute name="NamedConstructor" value="Audio">
+ <webidl> NamedConstructor=Audio(DOMString src)</webidl>
+ <ArgumentList>
+ <Argument name="src">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <InterfaceInheritance>
+ <Name name="HTMLMediaElement"/>
+ </InterfaceInheritance>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml
new file mode 100644
index 000000000..af0cde937
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Module name="acme" id="::acme">
+ <webidl>[NamespaceObject]
+module acme {
+
+ exception DeviceException { };
+
+ module pim {
+
+ [Constructor]
+ interface Contact { };
+
+ [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };
+ };
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NamespaceObject"/>
+ </ExtendedAttributeList>
+ <Exception name="DeviceException" id="::acme::DeviceException">
+ <webidl> exception DeviceException { };</webidl>
+ </Exception>
+ <Module name="pim" id="::acme::pim">
+ <webidl> module pim {
+
+ [Constructor]
+ interface Contact { };
+
+ [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };
+ };</webidl>
+ <Interface name="Contact" id="::acme::pim::Contact">
+ <webidl> [Constructor]
+ interface Contact { };</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor"/>
+ </ExtendedAttributeList>
+ </Interface>
+ <Interface name="CalendarEvent" id="::acme::pim::CalendarEvent">
+ <webidl> [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor"/>
+ <ExtendedAttribute name="NamedConstructor" value="RecurringEvent">
+ <ArgumentList>
+ <Argument name="freq">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ </Interface>
+ </Module>
+ </Module>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml
new file mode 100644
index 000000000..f64f116b6
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+};</webidl>
+ <Interface name="Query" id="::Query">
+ <webidl>[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NoInterfaceObject">
+ <webidl>NoInterfaceObject</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Operation name="lookupEntry" id="::Query::lookupEntry">
+ <webidl> any lookupEntry(unsigned long key);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="key">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml
new file mode 100644
index 000000000..8739e4432
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+};</webidl>
+ <Interface name="MyConstants" id="::MyConstants">
+ <webidl>interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};</webidl>
+ <Const name="ARE_WE_THERE_YET" value="false" id="::MyConstants::ARE_WE_THERE_YET">
+ <webidl> const boolean? ARE_WE_THERE_YET = false;</webidl>
+ <Type type="boolean" nullable="nullable"/>
+ </Const>
+ </Interface>
+ <Interface name="Node" id="::Node">
+ <webidl>interface Node {
+ readonly attribute DOMString? namespaceURI;
+};</webidl>
+ <Attribute readonly="readonly" name="namespaceURI" id="::Node::namespaceURI">
+ <webidl> readonly attribute DOMString? namespaceURI;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml
new file mode 100644
index 000000000..22d9fdd25
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+};
+interface B {
+};
+interface C {
+ void f(<ref>A</ref>? x);
+ void f(<ref>B</ref>? x);
+
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+};</webidl>
+ </Interface>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+};</webidl>
+ </Interface>
+ <Interface name="C" id="::C">
+ <webidl>interface C {
+ void f(<ref>A</ref>? x);
+ void f(<ref>B</ref>? x);
+
+};</webidl>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>A</ref>? x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="A" nullable="nullable"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>B</ref>? x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="B" nullable="nullable"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml
new file mode 100644
index 000000000..54aef1f87
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+};</webidl>
+ <Interface name="ColorCreator" id="::ColorCreator">
+ <webidl>interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+};</webidl>
+ <Operation name="createColor" id="::ColorCreator::createColor">
+ <webidl> object createColor(float v1, float v2, float v3, optional float alpha = 3.5);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="v1">
+ <Type type="float"/>
+ </Argument>
+ <Argument name="v2">
+ <Type type="float"/>
+ </Argument>
+ <Argument name="v3">
+ <Type type="float"/>
+ </Argument>
+ <Argument optional="optional" name="alpha" value="3.5">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml
new file mode 100644
index 000000000..db6da7a68
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+};
+
+interface B {
+};
+
+interface C {
+ void f(<ref>A</ref> x);
+ void f(<ref>B</ref> x);
+};
+
+interface A {
+void f(DOMString a);
+void f([AllowAny] DOMString a, DOMString b, float... c);
+void f();
+void f(long a, DOMString b, optional DOMString c, float... d);
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+};</webidl>
+ </Interface>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+};</webidl>
+ </Interface>
+ <Interface name="C" id="::C">
+ <webidl>interface C {
+ void f(<ref>A</ref> x);
+ void f(<ref>B</ref> x);
+};</webidl>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>A</ref> x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="A"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>B</ref> x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="B"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+void f(DOMString a);
+void f([AllowAny] DOMString a, DOMString b, float... c);
+void f();
+void f(long a, DOMString b, optional DOMString c, float... d);
+};</webidl>
+ <Operation name="f" id="::A::f">
+ <webidl> void f(DOMString a);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f([AllowAny] DOMString a, DOMString b, float... c);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="AllowAny">
+ <webidl>AllowAny</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="b">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument ellipsis="ellipsis" name="c">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f(long a, DOMString b, optional DOMString c, float... d);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <Type type="long"/>
+ </Argument>
+ <Argument name="b">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument optional="optional" name="c">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument ellipsis="ellipsis" name="d">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml
new file mode 100644
index 000000000..56c92517b
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+};</webidl>
+ <Interface name="StringMap2" id="::StringMap2">
+ <webidl>[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="OverrideBuiltins">
+ <webidl>OverrideBuiltins</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="length" id="::StringMap2::length">
+ <webidl> readonly attribute unsigned long length;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="lookup" id="::StringMap2::lookup">
+ <webidl> getter DOMString lookup(DOMString key);</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList>
+ <Argument name="key">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml
new file mode 100644
index 000000000..8d7dcb4e4
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+};</webidl>
+ <Interface name="Foo" id="::Foo">
+ <webidl>interface Foo {
+ attribute DOMString bar;
+};</webidl>
+ <Attribute name="bar" id="::Foo::bar">
+ <webidl> attribute DOMString bar;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Foo" partial="partial" id="::Foo">
+ <webidl>partial interface Foo {
+ attribute DOMString quux;
+};</webidl>
+ <Attribute name="quux" id="::Foo::quux">
+ <webidl> attribute DOMString quux;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml
new file mode 100644
index 000000000..46977a2d7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+};</webidl>
+ <Interface name="Primitives" id="::Primitives">
+ <webidl>interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+};</webidl>
+ <Attribute name="truth" id="::Primitives::truth">
+ <webidl> attribute boolean truth;</webidl>
+ <Type type="boolean"/>
+ </Attribute>
+ <Attribute name="character" id="::Primitives::character">
+ <webidl> attribute byte character;</webidl>
+ <Type type="byte"/>
+ </Attribute>
+ <Attribute name="value" id="::Primitives::value">
+ <webidl> attribute octet value;</webidl>
+ <Type type="octet"/>
+ </Attribute>
+ <Attribute name="number" id="::Primitives::number">
+ <webidl> attribute short number;</webidl>
+ <Type type="short"/>
+ </Attribute>
+ <Attribute name="positive" id="::Primitives::positive">
+ <webidl> attribute unsigned short positive;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ <Attribute name="big" id="::Primitives::big">
+ <webidl> attribute long big;</webidl>
+ <Type type="long"/>
+ </Attribute>
+ <Attribute name="bigpositive" id="::Primitives::bigpositive">
+ <webidl> attribute unsigned long bigpositive;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="bigbig" id="::Primitives::bigbig">
+ <webidl> attribute long long bigbig;</webidl>
+ <Type type="long long"/>
+ </Attribute>
+ <Attribute name="bigbigpositive" id="::Primitives::bigbigpositive">
+ <webidl> attribute unsigned long long bigbigpositive;</webidl>
+ <Type type="unsigned long long"/>
+ </Attribute>
+ <Attribute name="real" id="::Primitives::real">
+ <webidl> attribute float real;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="bigreal" id="::Primitives::bigreal">
+ <webidl> attribute double bigreal;</webidl>
+ <Type type="double"/>
+ </Attribute>
+ <Attribute name="realwithinfinity" id="::Primitives::realwithinfinity">
+ <webidl> attribute unrestricted float realwithinfinity;</webidl>
+ <Type type="unrestricted float"/>
+ </Attribute>
+ <Attribute name="bigrealwithinfinity" id="::Primitives::bigrealwithinfinity">
+ <webidl> attribute unrestricted double bigrealwithinfinity;</webidl>
+ <Type type="unrestricted double"/>
+ </Attribute>
+ <Attribute name="string" id="::Primitives::string">
+ <webidl> attribute DOMString string;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="bytes" id="::Primitives::bytes">
+ <webidl> attribute ByteString bytes;</webidl>
+ <Type type="ByteString"/>
+ </Attribute>
+ <Attribute name="date" id="::Primitives::date">
+ <webidl> attribute Date date;</webidl>
+ <Type type="Date"/>
+ </Attribute>
+ <Attribute name="regexp" id="::Primitives::regexp">
+ <webidl> attribute RegExp regexp;</webidl>
+ <Type type="RegExp"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml
new file mode 100644
index 000000000..2e56cd75e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+};</webidl>
+ <Interface name="Node" id="::Node">
+ <webidl>[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="PrototypeRoot">
+ <webidl>PrototypeRoot</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="nodeType" id="::Node::nodeType">
+ <webidl> readonly attribute unsigned short nodeType;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml
new file mode 100644
index 000000000..634fad55a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Person {
+ [PutForwards=full] readonly attribute <ref>Name</ref> name;
+ attribute unsigned short age;
+};</webidl>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person {
+ [PutForwards=full] readonly attribute <ref>Name</ref> name;
+ attribute unsigned short age;
+};</webidl>
+ <Attribute readonly="readonly" name="name" id="::Person::name">
+ <webidl> [PutForwards=full] readonly attribute <ref>Name</ref> name;</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="PutForwards" value="full">
+ <webidl>PutForwards</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type name="Name"/>
+ </Attribute>
+ <Attribute name="age" id="::Person::age">
+ <webidl> attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml
new file mode 100644
index 000000000..3b756ed68
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ boolean isMouseOver();
+
+ void setDimensions(<ref>Dimensions</ref> size);
+ void setDimensions(unsigned long width, unsigned long height);
+};</webidl>
+ <Interface name="Dimensions" id="::Dimensions">
+ <webidl>interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};</webidl>
+ <Attribute name="width" id="::Dimensions::width">
+ <webidl> attribute unsigned long width;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="height" id="::Dimensions::height">
+ <webidl> attribute unsigned long height;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ </Interface>
+ <Exception name="NoPointerDevice" id="::NoPointerDevice">
+ <webidl>exception NoPointerDevice { };</webidl>
+ </Exception>
+ <Interface name="Button" id="::Button">
+ <webidl>interface Button {
+
+ boolean isMouseOver();
+
+ void setDimensions(<ref>Dimensions</ref> size);
+ void setDimensions(unsigned long width, unsigned long height);
+};</webidl>
+ <Operation name="isMouseOver" id="::Button::isMouseOver">
+ <webidl> boolean isMouseOver();</webidl>
+ <Type type="boolean"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="setDimensions" id="::Button::setDimensions">
+ <webidl> void setDimensions(<ref>Dimensions</ref> size);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="size">
+ <Type name="Dimensions"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="setDimensions" id="::Button::setDimensions">
+ <webidl> void setDimensions(unsigned long width, unsigned long height);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="width">
+ <Type type="unsigned long"/>
+ </Argument>
+ <Argument name="height">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml
new file mode 100644
index 000000000..f97621668
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+};</webidl>
+ <Interface name="Counter" id="::Counter">
+ <webidl>interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+};</webidl>
+ <Attribute readonly="readonly" name="value" id="::Counter::value">
+ <webidl> [Replaceable] readonly attribute unsigned long value;</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Replaceable">
+ <webidl>Replaceable</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="increment" id="::Counter::increment">
+ <webidl> void increment();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml
new file mode 100644
index 000000000..d5f456417
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Canvas {
+ void drawPolygon(sequence&lt;float> coordinates);
+ sequence&lt;float> getInflectionPoints();
+};</webidl>
+ <Interface name="Canvas" id="::Canvas">
+ <webidl>interface Canvas {
+ void drawPolygon(sequence&lt;float> coordinates);
+ sequence&lt;float> getInflectionPoints();
+};</webidl>
+ <Operation name="drawPolygon" id="::Canvas::drawPolygon">
+ <webidl> void drawPolygon(sequence&lt;float> coordinates);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="coordinates">
+ <Type type="sequence">
+ <Type type="float"/>
+ </Type>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="getInflectionPoints" id="::Canvas::getInflectionPoints">
+ <webidl> sequence&lt;float> getInflectionPoints();</webidl>
+ <Type type="sequence">
+ <Type type="float"/>
+ </Type>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml
new file mode 100644
index 000000000..eb4219f8a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml
@@ -0,0 +1,296 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Transaction {
+ readonly attribute <ref>Account</ref> from;
+ readonly attribute <ref>Account</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute <ref>Account2</ref> from;
+ readonly attribute <ref>Account2</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+};</webidl>
+ <Interface name="Transaction" id="::Transaction">
+ <webidl>interface Transaction {
+ readonly attribute <ref>Account</ref> from;
+ readonly attribute <ref>Account</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};</webidl>
+ <Attribute readonly="readonly" name="from" id="::Transaction::from">
+ <webidl> readonly attribute <ref>Account</ref> from;</webidl>
+ <Type name="Account"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="to" id="::Transaction::to">
+ <webidl> readonly attribute <ref>Account</ref> to;</webidl>
+ <Type name="Account"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="amount" id="::Transaction::amount">
+ <webidl> readonly attribute float amount;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="description" id="::Transaction::description">
+ <webidl> readonly attribute DOMString description;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="number" id="::Transaction::number">
+ <webidl> readonly attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer;</webidl>
+ </Serializer>
+ </Interface>
+ <Interface name="Account" id="::Account">
+ <webidl>interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};</webidl>
+ <Attribute name="name" id="::Account::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation serializer="serializer" name="serialize" id="::Account::serialize">
+ <webidl> serializer DOMString serialize();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="Transaction2" id="::Transaction2">
+ <webidl>interface Transaction2 {
+ readonly attribute <ref>Account2</ref> from;
+ readonly attribute <ref>Account2</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};</webidl>
+ <Attribute readonly="readonly" name="from" id="::Transaction2::from">
+ <webidl> readonly attribute <ref>Account2</ref> from;</webidl>
+ <Type name="Account2"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="to" id="::Transaction2::to">
+ <webidl> readonly attribute <ref>Account2</ref> to;</webidl>
+ <Type name="Account2"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="amount" id="::Transaction2::amount">
+ <webidl> readonly attribute float amount;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="description" id="::Transaction2::description">
+ <webidl> readonly attribute DOMString description;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="number" id="::Transaction2::number">
+ <webidl> readonly attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { from, to, amount, description };</webidl>
+ <Map pattern="selection">
+ <PatternAttribute name="from"/>
+ <PatternAttribute name="to"/>
+ <PatternAttribute name="amount"/>
+ <PatternAttribute name="description"/>
+ </Map>
+ </Serializer>
+ </Interface>
+ <Interface name="Account2" id="::Account2">
+ <webidl>interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};</webidl>
+ <Attribute name="name" id="::Account2::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account2::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer attribute="number">
+ <webidl> serializer = number;</webidl>
+ </Serializer>
+ </Interface>
+ <Interface name="Account3" id="::Account3">
+ <webidl>interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};</webidl>
+ <Attribute name="name" id="::Account3::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account3::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { attribute };</webidl>
+ <Map pattern="all"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account4" id="::Account4">
+ <webidl>interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};</webidl>
+ <Operation getter="getter" name="getItem" id="::Account4::getItem">
+ <webidl> getter object getItem(unsigned long index);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Serializer>
+ <webidl> serializer = { getter };</webidl>
+ <Map pattern="getter"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account5" id="::Account5">
+ <webidl>interface Account5 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Account"/>
+ </InterfaceInheritance>
+ <Attribute name="secondname" id="::Account5::secondname">
+ <webidl> attribute DOMString secondname;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { inherit, secondname };</webidl>
+ <Map inherit="inherit" pattern="selection">
+ <PatternAttribute name="secondname"/>
+ </Map>
+ </Serializer>
+ </Interface>
+ <Interface name="Account6" id="::Account6">
+ <webidl>interface Account6 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Account"/>
+ </InterfaceInheritance>
+ <Attribute name="secondname" id="::Account6::secondname">
+ <webidl> attribute DOMString secondname;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { inherit, attribute };</webidl>
+ <Map inherit="inherit" pattern="all"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account7" id="::Account7">
+ <webidl>interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};</webidl>
+ <Attribute name="name" id="::Account7::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account7::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = [ name, number ];</webidl>
+ <List pattern="selection">
+ <PatternAttribute name="name"/>
+ <PatternAttribute name="number"/>
+ </List>
+ </Serializer>
+ </Interface>
+ <Interface name="Account8" id="::Account8">
+ <webidl>interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+};</webidl>
+ <Operation getter="getter" name="getItem" id="::Account8::getItem">
+ <webidl> getter object getItem(unsigned long index);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Serializer>
+ <webidl> serializer = [ getter ];</webidl>
+ <List pattern="getter"/>
+ </Serializer>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml
new file mode 100644
index 000000000..1986d190a
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation omittable="omittable" getter="getter" name="getProperty" id="::Dictionary::getProperty">
+ <webidl> omittable getter float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation omittable="omittable" setter="setter" name="setProperty" id="::Dictionary::setProperty">
+ <webidl> omittable setter void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml
new file mode 100644
index 000000000..03c14e16e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Point { };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);
+};</webidl>
+ <Interface name="Point" id="::Point">
+ <webidl>interface Point { };</webidl>
+ </Interface>
+ <Interface name="Circle" id="::Circle">
+ <webidl>interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);
+};</webidl>
+ <Attribute name="cx" id="::Circle::cx">
+ <webidl> attribute float cx;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cy" id="::Circle::cy">
+ <webidl> attribute float cy;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="radius" id="::Circle::radius">
+ <webidl> attribute float radius;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute static="static" readonly="readonly" name="triangulationCount" id="::Circle::triangulationCount">
+ <webidl> static readonly attribute long triangulationCount;</webidl>
+ <Type type="long"/>
+ </Attribute>
+ <Operation static="static" name="triangulate" id="::Circle::triangulate">
+ <webidl> static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);</webidl>
+ <Type name="Point"/>
+ <ArgumentList>
+ <Argument name="c1">
+ <Type name="Circle"/>
+ </Argument>
+ <Argument name="c2">
+ <Type name="Circle"/>
+ </Argument>
+ <Argument name="c3">
+ <Type name="Circle"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml
new file mode 100644
index 000000000..082ce4d34
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+};</webidl>
+ <Interface name="Student" id="::Student">
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="id" id="::Student::id">
+ <webidl> attribute unsigned long id;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute stringifier="stringifier" name="name" id="::Student::name">
+ <webidl> stringifier attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml
new file mode 100644
index 000000000..cdab1ccfc
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+};</webidl>
+ <Interface name="Student" id="::Student">
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="id" id="::Student::id">
+ <webidl> attribute unsigned long id;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="familyName" id="::Student::familyName">
+ <webidl> attribute DOMString? familyName;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ <Attribute name="givenName" id="::Student::givenName">
+ <webidl> attribute DOMString givenName;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation stringifier="stringifier">
+ <webidl> stringifier DOMString ();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml
new file mode 100644
index 000000000..4a18b80b7
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+ stringifier DOMString ();
+};</webidl>
+ <Operation stringifier="stringifier">
+ <webidl> stringifier DOMString ();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+ stringifier;
+};</webidl>
+ <Stringifier>
+ <webidl> stringifier;</webidl>
+ </Stringifier>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml
new file mode 100644
index 000000000..a57ae163f
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Interface name="Dog" id="::Dog">
+ <webidl>interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Attribute name="name" id="::Dog::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="owner" id="::Dog::owner">
+ <webidl> attribute DOMString owner;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation name="isMemberOfBreed" id="::Dog::isMemberOfBreed">
+ <webidl> boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="breedName">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="TreatNullAs" value="EmptyString">
+ <webidl>TreatNullAs</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml
new file mode 100644
index 000000000..17e71081d
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Interface name="Cat" id="::Cat">
+ <webidl>interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Attribute name="name" id="::Cat::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="owner" id="::Cat::owner">
+ <webidl> attribute DOMString owner;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation name="isMemberOfBreed" id="::Cat::isMemberOfBreed">
+ <webidl> boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="breedName">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="TreatUndefinedAs" value="EmptyString">
+ <webidl>TreatUndefinedAs</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml
new file mode 100644
index 000000000..785f6706e
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence&lt;<ref>Point</ref>> PointSequence;
+
+ interface Rect {
+ attribute <ref>Point</ref> topleft;
+ attribute <ref>Point</ref> bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute <ref>Rect</ref> bounds;
+
+ boolean pointWithinBounds(<ref>Point</ref> p);
+ boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);
+ };
+
+ typedef [Clamp] octet value;</webidl>
+ <Interface name="Point" id="::Point">
+ <webidl> interface Point {
+ attribute float x;
+ attribute float y;
+ };</webidl>
+ <Attribute name="x" id="::Point::x">
+ <webidl> attribute float x;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="y" id="::Point::y">
+ <webidl> attribute float y;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ </Interface>
+ <Typedef name="PointSequence" id="::PointSequence">
+ <webidl> typedef sequence&lt;<ref>Point</ref>> PointSequence;</webidl>
+ <Type type="sequence">
+ <Type name="Point"/>
+ </Type>
+ </Typedef>
+ <Interface name="Rect" id="::Rect">
+ <webidl> interface Rect {
+ attribute <ref>Point</ref> topleft;
+ attribute <ref>Point</ref> bottomright;
+ };</webidl>
+ <Attribute name="topleft" id="::Rect::topleft">
+ <webidl> attribute <ref>Point</ref> topleft;</webidl>
+ <Type name="Point"/>
+ </Attribute>
+ <Attribute name="bottomright" id="::Rect::bottomright">
+ <webidl> attribute <ref>Point</ref> bottomright;</webidl>
+ <Type name="Point"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Widget" id="::Widget">
+ <webidl> interface Widget {
+
+ readonly attribute <ref>Rect</ref> bounds;
+
+ boolean pointWithinBounds(<ref>Point</ref> p);
+ boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);
+ };</webidl>
+ <Attribute readonly="readonly" name="bounds" id="::Widget::bounds">
+ <webidl> readonly attribute <ref>Rect</ref> bounds;</webidl>
+ <Type name="Rect"/>
+ </Attribute>
+ <Operation name="pointWithinBounds" id="::Widget::pointWithinBounds">
+ <webidl> boolean pointWithinBounds(<ref>Point</ref> p);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="p">
+ <Type name="Point"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="allPointsWithinBounds" id="::Widget::allPointsWithinBounds">
+ <webidl> boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="ps">
+ <Type name="PointSequence"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Typedef name="value" id="::value">
+ <webidl> typedef [Clamp] octet value;</webidl>
+ <Type type="octet">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Clamp">
+ <webidl>Clamp</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ </Type>
+ </Typedef>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml
new file mode 100644
index 000000000..830fe62bc
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Suffixes {
+ void test(sequence&lt;DOMString[]?>? foo);
+};</webidl>
+ <Interface name="Suffixes" id="::Suffixes">
+ <webidl>interface Suffixes {
+ void test(sequence&lt;DOMString[]?>? foo);
+};</webidl>
+ <Operation name="test" id="::Suffixes::test">
+ <webidl> void test(sequence&lt;DOMString[]?>? foo);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="foo">
+ <Type type="sequence" nullable="nullable">
+ <Type type="array" nullable="nullable">
+ <Type type="DOMString"/>
+ </Type>
+ </Type>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml
new file mode 100644
index 000000000..7d0880799
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Union {
+ attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;
+};</webidl>
+ <Interface name="Union" id="::Union">
+ <webidl>interface Union {
+ attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;
+};</webidl>
+ <Attribute name="test" id="::Union::test">
+ <webidl> attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;</webidl>
+ <Type type="union">
+ <Type type="float"/>
+ <Type type="union">
+ <Type type="Date"/>
+ <Type name="Event"/>
+ </Type>
+ <Type type="union" nullable="nullable">
+ <Type name="Node"/>
+ <Type type="DOMString"/>
+ </Type>
+ </Type>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml
new file mode 100644
index 000000000..0bc9f7844
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+};</webidl>
+ <Interface name="IntegerSet" id="::IntegerSet">
+ <webidl>interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+};</webidl>
+ <Attribute readonly="readonly" name="cardinality" id="::IntegerSet::cardinality">
+ <webidl> readonly attribute unsigned long cardinality;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="union" id="::IntegerSet::union">
+ <webidl> void union(long... ints);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument ellipsis="ellipsis" name="ints">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="intersection" id="::IntegerSet::intersection">
+ <webidl> void intersection(long... ints);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument ellipsis="ellipsis" name="ints">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>