Bug 1457047 [wpt PR 10645] - Update webidl2.js to v10.2.1, a=testonly
authorGeoffrey Sneddon <me@gsnedders.com>
Tue, 01 May 2018 15:02:42 +0000
changeset 472676 21a5a8d11df33df8681ed3468f6b67b11e411d66
parent 472675 052f56ef82ee6233ea88fcdb0607d7305dee653d
child 472677 13ae46f5236c5426ad952bd7bbc8f22f91257d9c
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1457047, 10645
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1457047 [wpt PR 10645] - Update webidl2.js to v10.2.1, a=testonly Automatic update from web-platform-testsMerge pull request #10645 from csnardi/update-webidl2 Update webidl2.js to v10.2.1 -- wpt-commits: 9f5c74dc3a633802acaa93ac325b11fff8c739f1 wpt-pr: 10645
testing/web-platform/tests/resources/idlharness.js
testing/web-platform/tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
testing/web-platform/tests/resources/webidl2/.travis.yml
testing/web-platform/tests/resources/webidl2/CHANGELOG.md
testing/web-platform/tests/resources/webidl2/README.md
testing/web-platform/tests/resources/webidl2/lib/webidl2.js
testing/web-platform/tests/resources/webidl2/lib/writer.js
testing/web-platform/tests/resources/webidl2/package-lock.json
testing/web-platform/tests/resources/webidl2/package.json
testing/web-platform/tests/resources/webidl2/test/invalid.js
testing/web-platform/tests/resources/webidl2/test/invalid/idl/iterator.widl
testing/web-platform/tests/resources/webidl2/test/invalid/idl/no-semicolon-callback.widl
testing/web-platform/tests/resources/webidl2/test/invalid/idl/no-semicolon.widl
testing/web-platform/tests/resources/webidl2/test/invalid/idl/stray-slash.widl
testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.idl
testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.widl
testing/web-platform/tests/resources/webidl2/test/invalid/json/array.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/caller.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/dict-required-default.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/duplicate.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/enum.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/exception.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/iterator.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/maplike-1type.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/module.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/no-semicolon-callback.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/no-semicolon.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableany.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableobjects.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/promise-with-extended-attribute.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/raises.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/readonly-iterable.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key-with-extended-attribute.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/scopedname.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/setlike-2types.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/setter-creator.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/special-omittable.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/stray-slash.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/stringconstants.json
testing/web-platform/tests/resources/webidl2/test/invalid/json/typedef-nested.json
testing/web-platform/tests/resources/webidl2/test/syntax.js
testing/web-platform/tests/resources/webidl2/test/syntax/idl/extended-attributes.widl
testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterator.widl
testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-union.idl
testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-union.widl
testing/web-platform/tests/resources/webidl2/test/syntax/json/allowany.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/attributes.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/callback.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/constants.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/constructor.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation-dos.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/enum.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/equivalent-decl.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/extended-attributes.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/generic.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/getter-setter.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/implements.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/indexed-properties.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/inherits-getter.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/interface-inherits.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/iterable.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/legacyiterable.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/maplike.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/mixin.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/namedconstructor.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/namespace.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/nullable.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/nullableobjects.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/overloading.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/overridebuiltins.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/partial-interface.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/primitives.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/prototyperoot.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/putforwards.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/record.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/reg-operations.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/replaceable.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/sequence.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/setlike.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/static.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier-custom.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasnull.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasundefined.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-union.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/typesuffixes.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json
testing/web-platform/tests/resources/webidl2/test/syntax/json/variadic-operations.json
testing/web-platform/tests/resources/webidl2/test/util/acquire.js
testing/web-platform/tests/resources/webidl2/test/util/collect.js
testing/web-platform/tests/resources/webidl2/test/writer.js
--- a/testing/web-platform/tests/resources/idlharness.js
+++ b/testing/web-platform/tests/resources/idlharness.js
@@ -2160,17 +2160,17 @@ IdlInterface.prototype.test_to_json_oper
     }
 };
 
 //@}
 IdlInterface.prototype.test_member_iterable = function(member)
 //@{
 {
     var interfaceName = this.name;
-    var isPairIterator = member.idlType instanceof Array;
+    var isPairIterator = member.idlType.length === 2;
     test(function()
     {
         var descriptor = Object.getOwnPropertyDescriptor(self[interfaceName].prototype, Symbol.iterator);
         assert_true(descriptor.writable, "property should be writable");
         assert_true(descriptor.configurable, "property should be configurable");
         assert_false(descriptor.enumerable, "property should not be enumerable");
         assert_equals(self[interfaceName].prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name");
     }, "Testing Symbol.iterator property of iterable interface " + interfaceName);
--- a/testing/web-platform/tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
+++ b/testing/web-platform/tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
@@ -171,17 +171,17 @@
             {
                 "message": "assert_equals: expected \"string\" but got \"object\"",
                 "name": "Test toJSON operation of M",
                 "properties": {},
                 "stack": "(implementation-defined)",
                 "status_string": "FAIL"
             },
             {
-                "message": "assert_true: {\"sequence\":false,\"generic\":null,\"nullable\":false,\"union\":false,\"idlType\":\"DOMException\"} is not an appropriate return value for the toJSON operation of N expected true got false",
+                "message": "assert_true: {\"type\":\"return-type\",\"sequence\":false,\"generic\":null,\"nullable\":false,\"union\":false,\"idlType\":\"DOMException\"} is not an appropriate return value for the toJSON operation of N expected true got false",
                 "name": "Test toJSON operation of N",
                 "properties": {},
                 "stack": "(implementation-defined)",
                 "status_string": "FAIL"
             }
         ],
         "type": "complete"
     }
--- a/testing/web-platform/tests/resources/webidl2/.travis.yml
+++ b/testing/web-platform/tests/resources/webidl2/.travis.yml
@@ -1,4 +1,5 @@
 language: node_js
 node_js:
   - node
   - lts/*
+  - 6
--- a/testing/web-platform/tests/resources/webidl2/CHANGELOG.md
+++ b/testing/web-platform/tests/resources/webidl2/CHANGELOG.md
@@ -1,34 +1,102 @@
 # Change Log
 
+## [v10.2.0](https://github.com/w3c/webidl2.js/tree/v10.2.0) (2018-01-30)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v10.1.0...v10.2.0)
+
+**Merged pull requests:**
+
+- Type on union idlType [\#135](https://github.com/w3c/webidl2.js/pull/135) ([saschanaz](https://github.com/saschanaz))
+- feat: add argument/return type [\#134](https://github.com/w3c/webidl2.js/pull/134) ([saschanaz](https://github.com/saschanaz))
+- feat: add dictionary/typedef-type [\#133](https://github.com/w3c/webidl2.js/pull/133) ([saschanaz](https://github.com/saschanaz))
+- feat: add const-type for idlTypes  [\#132](https://github.com/w3c/webidl2.js/pull/132) ([saschanaz](https://github.com/saschanaz))
+- feat: add types on idlTypes [\#131](https://github.com/w3c/webidl2.js/pull/131) ([saschanaz](https://github.com/saschanaz))
+- Auto acquisition for parser result changes [\#130](https://github.com/w3c/webidl2.js/pull/130) ([saschanaz](https://github.com/saschanaz))
+
+## [v10.1.0](https://github.com/w3c/webidl2.js/tree/v10.1.0) (2018-01-19)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v10.0.0...v10.1.0)
+
+**Closed issues:**
+
+- Support `raises` and `setraises` [\#128](https://github.com/w3c/webidl2.js/issues/128)
+- Support `legacycaller` [\#127](https://github.com/w3c/webidl2.js/issues/127)
+- Improve "No semicolon after enum" message [\#119](https://github.com/w3c/webidl2.js/issues/119)
+
+**Merged pull requests:**
+
+- Let error messages include the current definition name [\#129](https://github.com/w3c/webidl2.js/pull/129) ([saschanaz](https://github.com/saschanaz))
+
+## [v10.0.0](https://github.com/w3c/webidl2.js/tree/v10.0.0) (2017-12-20)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v9.0.0...v10.0.0)
+
+**Closed issues:**
+
+-  Always return an array for idlType, etc. [\#113](https://github.com/w3c/webidl2.js/issues/113)
+- Maintain writer.js or not? [\#109](https://github.com/w3c/webidl2.js/issues/109)
+
+**Merged pull requests:**
+
+- Remove typeExtAttrs from docs [\#124](https://github.com/w3c/webidl2.js/pull/124) ([saschanaz](https://github.com/saschanaz))
+- Remove iterator documentation [\#123](https://github.com/w3c/webidl2.js/pull/123) ([saschanaz](https://github.com/saschanaz))
+- Maintain writer.js [\#122](https://github.com/w3c/webidl2.js/pull/122) ([saschanaz](https://github.com/saschanaz))
+- BREAKING CHANGE: remove deprecated iterator operation [\#121](https://github.com/w3c/webidl2.js/pull/121) ([saschanaz](https://github.com/saschanaz))
+- Use for-of on tests [\#120](https://github.com/w3c/webidl2.js/pull/120) ([saschanaz](https://github.com/saschanaz))
+- docs\(README\): iterables ildType is always array [\#118](https://github.com/w3c/webidl2.js/pull/118) ([marcoscaceres](https://github.com/marcoscaceres))
+
+## [v9.0.0](https://github.com/w3c/webidl2.js/tree/v9.0.0) (2017-11-30)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v8.1.0...v9.0.0)
+
+**Closed issues:**
+
+- Code quality [\#116](https://github.com/w3c/webidl2.js/issues/116)
+- Unable to parse HTMLAllCollection interface [\#114](https://github.com/w3c/webidl2.js/issues/114)
+- Add support for mixin syntax [\#112](https://github.com/w3c/webidl2.js/issues/112)
+- Whitespace issues [\#111](https://github.com/w3c/webidl2.js/issues/111)
+
+**Merged pull requests:**
+
+- Consistent array type for iterable.idlType [\#117](https://github.com/w3c/webidl2.js/pull/117) ([saschanaz](https://github.com/saschanaz))
+-  Revert "chore: drop Node 6 support \(\#102\)" [\#115](https://github.com/w3c/webidl2.js/pull/115) ([TimothyGu](https://github.com/TimothyGu))
+
+## [v8.1.0](https://github.com/w3c/webidl2.js/tree/v8.1.0) (2017-11-03)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v8.0.1...v8.1.0)
+
+**Closed issues:**
+
+- Extended Attributes `rhs` should always be there [\#96](https://github.com/w3c/webidl2.js/issues/96)
+
+**Merged pull requests:**
+
+- Always add rhs property [\#110](https://github.com/w3c/webidl2.js/pull/110) ([saschanaz](https://github.com/saschanaz))
+
 ## [v8.0.1](https://github.com/w3c/webidl2.js/tree/v8.0.1) (2017-11-03)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v8.0.0...v8.0.1)
 
 **Fixed bugs:**
 
 - Comment order parsing bug  [\#107](https://github.com/w3c/webidl2.js/issues/107)
 
 **Merged pull requests:**
 
-- Remove m postfix from all\_ws\(\) [\#108](https://github.com/w3c/webidl2.js/pull/108) ([SaschaNaz](https://github.com/SaschaNaz))
+- Remove m postfix from all\_ws\(\) [\#108](https://github.com/w3c/webidl2.js/pull/108) ([saschanaz](https://github.com/saschanaz))
 
 ## [v8.0.0](https://github.com/w3c/webidl2.js/tree/v8.0.0) (2017-11-03)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v7.0.0...v8.0.0)
 
 **Closed issues:**
 
 - Remove creators support [\#100](https://github.com/w3c/webidl2.js/issues/100)
 - Add mixin support [\#92](https://github.com/w3c/webidl2.js/issues/92)
 
 **Merged pull requests:**
 
-- Support mixins + includes statements [\#105](https://github.com/w3c/webidl2.js/pull/105) ([SaschaNaz](https://github.com/SaschaNaz))
+- Support mixins + includes statements [\#105](https://github.com/w3c/webidl2.js/pull/105) ([saschanaz](https://github.com/saschanaz))
 - chore: drop Node 6 support [\#102](https://github.com/w3c/webidl2.js/pull/102) ([marcoscaceres](https://github.com/marcoscaceres))
-- BREAKING CHANGE: drop creator support [\#101](https://github.com/w3c/webidl2.js/pull/101) ([SaschaNaz](https://github.com/SaschaNaz))
+- BREAKING CHANGE: drop creator support [\#101](https://github.com/w3c/webidl2.js/pull/101) ([saschanaz](https://github.com/saschanaz))
 - Normalize some whitespace to pass wpt's lint [\#99](https://github.com/w3c/webidl2.js/pull/99) ([foolip](https://github.com/foolip))
 
 ## [v7.0.0](https://github.com/w3c/webidl2.js/tree/v7.0.0) (2017-10-27)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v6.1.0...v7.0.0)
 
 **Closed issues:**
 
 - Type conversion on default values is destructive  [\#94](https://github.com/w3c/webidl2.js/issues/94)
@@ -49,17 +117,17 @@
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v6.0.0...v6.0.1)
 
 **Closed issues:**
 
 - Enum values should be objects [\#86](https://github.com/w3c/webidl2.js/issues/86)
 
 **Merged pull requests:**
 
-- Use ES2015 syntax for tests [\#88](https://github.com/w3c/webidl2.js/pull/88) ([SaschaNaz](https://github.com/SaschaNaz))
+- Use ES2015 syntax for tests [\#88](https://github.com/w3c/webidl2.js/pull/88) ([saschanaz](https://github.com/saschanaz))
 
 ## [v6.0.0](https://github.com/w3c/webidl2.js/tree/v6.0.0) (2017-10-17)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v5.0.0...v6.0.0)
 
 **Merged pull requests:**
 
 - BREAKING CHANGE: ret enum value as object [\#87](https://github.com/w3c/webidl2.js/pull/87) ([marcoscaceres](https://github.com/marcoscaceres))
 
@@ -68,80 +136,80 @@
 
 **Closed issues:**
 
 - Unable to parse annotated types in generics [\#83](https://github.com/w3c/webidl2.js/issues/83)
 - Drop support for Node 4, move to 6 LTS [\#82](https://github.com/w3c/webidl2.js/issues/82)
 
 **Merged pull requests:**
 
-- BREAKING CHANGE: Use ES2015 syntax [\#84](https://github.com/w3c/webidl2.js/pull/84) ([SaschaNaz](https://github.com/SaschaNaz))
+- BREAKING CHANGE: Use ES2015 syntax [\#84](https://github.com/w3c/webidl2.js/pull/84) ([saschanaz](https://github.com/saschanaz))
 
 ## [v4.2.0](https://github.com/w3c/webidl2.js/tree/v4.2.0) (2017-10-16)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v4.1.0...v4.2.0)
 
 **Closed issues:**
 
 - Remove legacy caller support [\#78](https://github.com/w3c/webidl2.js/issues/78)
 - Should report error for using duplicate names [\#77](https://github.com/w3c/webidl2.js/issues/77)
 
 **Merged pull requests:**
 
-- Check duplicated names [\#80](https://github.com/w3c/webidl2.js/pull/80) ([SaschaNaz](https://github.com/SaschaNaz))
-- Remove legacycaller [\#79](https://github.com/w3c/webidl2.js/pull/79) ([SaschaNaz](https://github.com/SaschaNaz))
+- Check duplicated names [\#80](https://github.com/w3c/webidl2.js/pull/80) ([saschanaz](https://github.com/saschanaz))
+- Remove legacycaller [\#79](https://github.com/w3c/webidl2.js/pull/79) ([saschanaz](https://github.com/saschanaz))
 - Add "sequence" property to IDL Type AST definition [\#76](https://github.com/w3c/webidl2.js/pull/76) ([lerouche](https://github.com/lerouche))
 
 ## [v4.1.0](https://github.com/w3c/webidl2.js/tree/v4.1.0) (2017-07-04)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v4.0.0...v4.1.0)
 
 **Closed issues:**
 
 - Parsing error for annonated inner types of generic types [\#71](https://github.com/w3c/webidl2.js/issues/71)
 
 **Merged pull requests:**
 
-- Support TypeWithExtendedAttributes on generics [\#75](https://github.com/w3c/webidl2.js/pull/75) ([SaschaNaz](https://github.com/SaschaNaz))
+- Support TypeWithExtendedAttributes on generics [\#75](https://github.com/w3c/webidl2.js/pull/75) ([saschanaz](https://github.com/saschanaz))
 
 ## [v4.0.0](https://github.com/w3c/webidl2.js/tree/v4.0.0) (2017-06-27)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v3.0.2...v4.0.0)
 
 **Closed issues:**
 
 - Remove serializer-related productions [\#73](https://github.com/w3c/webidl2.js/issues/73)
 - Records don't seem to be working right [\#72](https://github.com/w3c/webidl2.js/issues/72)
 - Document namespace member output [\#59](https://github.com/w3c/webidl2.js/issues/59)
 
 **Merged pull requests:**
 
 - BREAKING CHANGE: remove serializers \(closes \#73\) [\#74](https://github.com/w3c/webidl2.js/pull/74) ([marcoscaceres](https://github.com/marcoscaceres))
-- Add documentation for namespaces [\#70](https://github.com/w3c/webidl2.js/pull/70) ([SaschaNaz](https://github.com/SaschaNaz))
+- Add documentation for namespaces [\#70](https://github.com/w3c/webidl2.js/pull/70) ([saschanaz](https://github.com/saschanaz))
 
 ## [v3.0.2](https://github.com/w3c/webidl2.js/tree/v3.0.2) (2017-05-29)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v3.0.1...v3.0.2)
 
 **Closed issues:**
 
 - Whitespace issues [\#64](https://github.com/w3c/webidl2.js/issues/64)
 
 **Merged pull requests:**
 
-- Test for latest LTS/stable node versions [\#69](https://github.com/w3c/webidl2.js/pull/69) ([SaschaNaz](https://github.com/SaschaNaz))
+- Test for latest LTS/stable node versions [\#69](https://github.com/w3c/webidl2.js/pull/69) ([saschanaz](https://github.com/saschanaz))
 
 ## [v3.0.1](https://github.com/w3c/webidl2.js/tree/v3.0.1) (2017-05-18)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v2.4.0...v3.0.1)
 
 **Closed issues:**
 
 - Is array syntax dead? [\#66](https://github.com/w3c/webidl2.js/issues/66)
 - Remove exceptions support [\#65](https://github.com/w3c/webidl2.js/issues/65)
 
 **Merged pull requests:**
 
-- Fix whitespace error on parsing extended attributes [\#68](https://github.com/w3c/webidl2.js/pull/68) ([SaschaNaz](https://github.com/SaschaNaz))
-- Remove deprecated IDL arrays and exceptions [\#67](https://github.com/w3c/webidl2.js/pull/67) ([SaschaNaz](https://github.com/SaschaNaz))
+- Fix whitespace error on parsing extended attributes [\#68](https://github.com/w3c/webidl2.js/pull/68) ([saschanaz](https://github.com/saschanaz))
+- Remove deprecated IDL arrays and exceptions [\#67](https://github.com/w3c/webidl2.js/pull/67) ([saschanaz](https://github.com/saschanaz))
 
 ## [v2.4.0](https://github.com/w3c/webidl2.js/tree/v2.4.0) (2017-04-12)
 [Full Changelog](https://github.com/w3c/webidl2.js/compare/v2.1.0...v2.4.0)
 
 **Closed issues:**
 
 - Add support for Annotated Types [\#60](https://github.com/w3c/webidl2.js/issues/60)
 - Question: Convert WebIDL -\> Javascript [\#56](https://github.com/w3c/webidl2.js/issues/56)
@@ -152,17 +220,17 @@
 - Export is not AMD compatible [\#48](https://github.com/w3c/webidl2.js/issues/48)
 - Can't represent large constants [\#21](https://github.com/w3c/webidl2.js/issues/21)
 
 **Merged pull requests:**
 
 - Update webidl2.js [\#63](https://github.com/w3c/webidl2.js/pull/63) ([tqeto](https://github.com/tqeto))
 - Remove support for MapClass \(no longer valid in WebIDL\) [\#62](https://github.com/w3c/webidl2.js/pull/62) ([dontcallmedom](https://github.com/dontcallmedom))
 - Add support for annotated types [\#61](https://github.com/w3c/webidl2.js/pull/61) ([dontcallmedom](https://github.com/dontcallmedom))
-- Support namespaces [\#58](https://github.com/w3c/webidl2.js/pull/58) ([SaschaNaz](https://github.com/SaschaNaz))
+- Support namespaces [\#58](https://github.com/w3c/webidl2.js/pull/58) ([saschanaz](https://github.com/saschanaz))
 - Add support for records [\#57](https://github.com/w3c/webidl2.js/pull/57) ([TimothyGu](https://github.com/TimothyGu))
 - Refactor [\#50](https://github.com/w3c/webidl2.js/pull/50) ([marcoscaceres](https://github.com/marcoscaceres))
 - feat\(lib\): add AMD export support \(closes \#48\) [\#49](https://github.com/w3c/webidl2.js/pull/49) ([marcoscaceres](https://github.com/marcoscaceres))
 
 ## [v2.1.0](https://github.com/w3c/webidl2.js/tree/v2.1.0) (2016-08-12)
 **Closed issues:**
 
 - Exception when parsing test/syntax/idl/typedef.widl [\#46](https://github.com/w3c/webidl2.js/issues/46)
--- a/testing/web-platform/tests/resources/webidl2/README.md
+++ b/testing/web-platform/tests/resources/webidl2/README.md
@@ -305,17 +305,16 @@ The fields are as follows:
 
 ### Typedef
 
 A typedef looks like this:
 
 ```JS
 {
   "type": "typedef",
-  "typeExtAttrs": [],
   "idlType": {
     "sequence": true,
     "generic": "sequence",
     "nullable": false,
     "union": false,
     "idlType": {
       "sequence": false,
       "generic": null,
@@ -331,18 +330,16 @@ A typedef looks like this:
 
 
 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:
 
 ```JS
 {
   "type": "implements",
@@ -484,44 +481,16 @@ 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).
 
-### Iterator Member
-
-Iterator members look like this
-
-```JS
-{
-  "type": "iterator",
-  "getter": false,
-  "setter": false,
-  "deleter": false,
-  "static": false,
-  "stringifier": false,
-  "idlType": {
-    "sequence": false,
-    "generic": null,
-    "nullable": 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:
 
 ```JS
 {
   "arguments": [{
     "optional": false,
@@ -606,17 +575,17 @@ These appear as members of interfaces th
   "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.
+* `idlType`: An array with one or more [IDL Types](#idl-type) 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
 initialized and up to date:
--- a/testing/web-platform/tests/resources/webidl2/lib/webidl2.js
+++ b/testing/web-platform/tests/resources/webidl2/lib/webidl2.js
@@ -1,38 +1,87 @@
 "use strict";
 
 (() => {
+  // These regular expressions use the sticky flag so they will only match at
+  // the current location (ie. the offset of lastIndex).
+  const tokenRe = {
+    // This expression uses a lookahead assertion to catch false matches
+    // against integers early.
+    "float": /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y,
+    "integer": /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y,
+    "identifier": /[A-Z_a-z][0-9A-Z_a-z-]*/y,
+    "string": /"[^"]*"/y,
+    "whitespace": /[\t\n\r ]+/y,
+    "comment": /((\/(\/.*|\*([^*]|\*[^\/])*\*\/)[\t\n\r ]*)+)/y,
+    "other": /[^\t\n\r 0-9A-Z_a-z]/y
+  };
+
+  function attemptTokenMatch(str, type, re, lastIndex, tokens) {
+    re.lastIndex = lastIndex;
+    const result = re.exec(str);
+    if (result) {
+      tokens.push({ type, value: result[0] });
+      return re.lastIndex;
+    }
+    return -1;
+  }
+
   function tokenise(str) {
     const tokens = [];
-    const 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]/
-    };
-    const types = ["float", "integer", "identifier", "string", "whitespace", "other"];
-    while (str.length > 0) {
-      let matched = false;
-      for (var i in types) {
-        const type = types[i];
-        str = str.replace(re[type], tok => {
-          tokens.push({ type, value: tok });
-          matched = true;
-          return "";
-        });
-        if (matched) break;
+    let lastIndex = 0;
+    while (lastIndex < str.length) {
+      const nextChar = str.charAt(lastIndex);
+      let result = -1;
+      if (/[-0-9.]/.test(nextChar)) {
+        result = attemptTokenMatch(str, "float", tokenRe.float, lastIndex,
+                                   tokens);
+        if (result === -1) {
+          result = attemptTokenMatch(str, "integer", tokenRe.integer, lastIndex,
+                                     tokens);
+        }
+        if (result === -1) {
+          // '-' and '.' can also match "other".
+          result = attemptTokenMatch(str, "other", tokenRe.other,
+                                     lastIndex, tokens);
+        }
+      } else if (/[A-Z_a-z]/.test(nextChar)) {
+        result = attemptTokenMatch(str, "identifier", tokenRe.identifier,
+                                   lastIndex, tokens);
+      } else if (nextChar === '"') {
+        result = attemptTokenMatch(str, "string", tokenRe.string,
+                                   lastIndex, tokens);
+        if (result === -1) {
+          // '"' can also match "other".
+          result = attemptTokenMatch(str, "other", tokenRe.other,
+                                     lastIndex, tokens);
+        }
+      } else if (/[\t\n\r ]/.test(nextChar)) {
+        result = attemptTokenMatch(str, "whitespace", tokenRe.whitespace,
+                                   lastIndex, tokens);
+      } else if (nextChar === '/') {
+        // The parser expects comments to be labelled as "whitespace".
+        result = attemptTokenMatch(str, "whitespace", tokenRe.comment,
+                                   lastIndex, tokens);
+        if (result === -1) {
+          // '/' can also match "other".
+          result = attemptTokenMatch(str, "other", tokenRe.other,
+                                     lastIndex, tokens);
+        }
+      } else {
+        result = attemptTokenMatch(str, "other", tokenRe.other,
+                                   lastIndex, tokens);
       }
-      if (matched) continue;
-      throw new Error("Token stream not progressing");
+      if (result === -1) {
+        throw new Error("Token stream not progressing");
+      }
+      lastIndex = result;
     }
     return tokens;
-  };
+  }
 
   class WebIDLParseError {
     constructor(str, line, input, tokens) {
       this.message = str;
       this.line = line;
       this.input = input;
       this.tokens = tokens;
     }
@@ -41,172 +90,193 @@
       return `${this.message}, line ${this.line} (tokens: '${this.input}')\n${JSON.stringify(this.tokens, null, 4)}`;
     }
   }
 
   function parse(tokens, opt) {
     let line = 1;
     tokens = tokens.slice();
     const names = new Map();
+    let current = null;
 
     const FLOAT = "float";
     const INT = "integer";
     const ID = "identifier";
     const STR = "string";
     const OTHER = "other";
 
     const EMPTY_OPERATION = Object.freeze({
       type: "operation",
       getter: false,
       setter: false,
       deleter: false,
-      "static": false,
+      static: false,
       stringifier: false
     });
 
     function error(str) {
       let tok = "";
       let numTokens = 0;
       const maxTokens = 5;
       while (numTokens < maxTokens && tokens.length > numTokens) {
         tok += tokens[numTokens].value;
         numTokens++;
       }
-      throw new WebIDLParseError(str, line, tok, tokens.slice(0, maxTokens));
-    };
+      
+      let message;
+      if (current) {
+        message = `Got an error during or right after parsing \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`: ${str}`
+      }
+      else {
+        // throwing before any valid definition
+        message = `Got an error before parsing any named definition: ${str}`;
+      }
+
+      throw new WebIDLParseError(message, line, tok, tokens.slice(0, maxTokens));
+    }
 
     function sanitize_name(name, type) {
       if (names.has(name)) {
         error(`The name "${name}" of type "${names.get(name)}" is already seen`);
       }
       names.set(name, type);
       return name;
     }
 
     let last_token = null;
 
     function consume(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(/^_/, "");
+        if (type === ID && last_token.value.startsWith('_'))
+          last_token.value = last_token.value.substring(1);
         return last_token;
       }
-    };
+    }
+
+    function count(str, char) {
+      let total = 0;
+      for (let i = str.indexOf(char); i !== -1; i = str.indexOf(char, i + 1)) {
+        ++total;
+      }
+      return total;
+    }
 
     function ws() {
       if (!tokens.length) return;
       if (tokens[0].type === "whitespace") {
         const t = tokens.shift();
-        t.value.replace(/\n/g, m => {
-          line++;
-          return m;
-        });
+        line += count(t.value, '\n');
         return t;
       }
+    }
+
+    const all_ws_re = {
+      "ws": /([\t\n\r ]+)/y,
+      "line-comment": /\/\/(.*)\r?\n?/y,
+      "multiline-comment": /\/\*((?:[^*]|\*[^/])*)\*\//y
     };
-
     function all_ws(store, pea) { // pea == post extended attribute, tpea = same for types
       const t = { type: "whitespace", value: "" };
       while (true) {
         const w = ws();
         if (!w) break;
         t.value += w.value;
       }
       if (t.value.length > 0) {
         if (store) {
           let w = t.value;
-          const re = {
-            "ws": /^([\t\n\r ]+)/,
-            "line-comment": /^\/\/(.*)\r?\n?/,
-            "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\//
-          };
-          const wsTypes = [];
-          for (var k in re) wsTypes.push(k);
-          while (w.length) {
+          let lastIndex = 0;
+          while (lastIndex < w.length) {
             let matched = false;
-            for (var i in wsTypes) {
-              const type = wsTypes[i];
-              w = w.replace(re[type], (tok, m1) => {
-                store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 });
+            // Servo doesn't support using "const" in this construction yet.
+            // See https://github.com/servo/servo/issues/20231.
+            // |type| can be made const once Servo supports it.
+            for (let type in all_ws_re) {
+              const re = all_ws_re[type];
+              re.lastIndex = lastIndex;
+              const result = re.exec(w);
+              if (result) {
+                store.push({ type: type + (pea ? ("-" + pea) : ""), value: result[1] });
                 matched = true;
-                return "";
-              });
-              if (matched) break;
+                lastIndex = re.lastIndex;
+                break;
+              }
             }
-            if (matched) continue;
-            throw new Error("Surprising white space construct."); // this shouldn't happen
+            if (!matched)
+              throw new Error("Surprising white space construct."); // this shouldn't happen
           }
         }
         return t;
       }
-    };
+    }
 
     function integer_type() {
       let 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");
-    };
+    }
 
     function float_type() {
       let 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");
-    };
+    }
 
     function primitive_type() {
       const 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";
-    };
+    }
 
     function const_value() {
       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" };
       const ret = consume(FLOAT) || consume(INT);
       if (ret) return { type: "number", value: ret.value };
       const tok = consume(OTHER, "-");
       if (tok) {
         if (consume(ID, "Infinity")) return { type: "Infinity", negative: true };
         else tokens.unshift(tok);
       }
-    };
+    }
 
     function type_suffix(obj) {
       while (true) {
         all_ws();
         if (consume(OTHER, "?")) {
           if (obj.nullable) error("Can't nullable more than once");
           obj.nullable = true;
         } else return;
       }
-    };
+    }
 
-    function single_type() {
+    function single_type(typeName) {
       const prim = primitive_type();
-      const ret = { sequence: false, generic: null, nullable: false, union: false };
+      const ret = { type: typeName || null, sequence: false, generic: null, nullable: false, union: false };
       let name;
       let value;
       if (prim) {
         ret.idlType = prim;
       } else if (name = consume(ID)) {
         value = name.value;
         all_ws();
         // Generic types
@@ -214,17 +284,17 @@
           // backwards compat
           if (value === "sequence") {
             ret.sequence = true;
           }
           ret.generic = value;
           const types = [];
           do {
             all_ws();
-            types.push(type_with_extended_attributes() || error("Error parsing generic type " + value));
+            types.push(type_with_extended_attributes(typeName) || error("Error parsing generic type " + value));
             all_ws();
           }
           while (consume(OTHER, ","));
           if (value === "sequence") {
             if (types.length !== 1) error("A sequence must have exactly one subtype");
           } else if (value === "record") {
             if (types.length !== 2) error("A record must have exactly two subtypes");
             if (!/^(DOMString|USVString|ByteString)$/.test(types[0].idlType)) {
@@ -243,56 +313,56 @@
           ret.idlType = value;
         }
       } else {
         return;
       }
       type_suffix(ret);
       if (ret.nullable && ret.idlType === "any") error("Type any cannot be made nullable");
       return ret;
-    };
+    }
 
-    function union_type() {
+    function union_type(typeName) {
       all_ws();
       if (!consume(OTHER, "(")) return;
-      const ret = { sequence: false, generic: null, nullable: false, union: true, idlType: [] };
+      const ret = { type: typeName || null, sequence: false, generic: null, nullable: false, union: true, idlType: [] };
       const fst = type_with_extended_attributes() || error("Union type with no content");
       ret.idlType.push(fst);
       while (true) {
         all_ws();
         if (!consume(ID, "or")) break;
         const typ = type_with_extended_attributes() || error("No type after 'or' in union type");
         ret.idlType.push(typ);
       }
       if (!consume(OTHER, ")")) error("Unterminated union type");
       type_suffix(ret);
       return ret;
-    };
+    }
 
-    function type() {
-      return single_type() || union_type();
-    };
+    function type(typeName) {
+      return single_type(typeName) || union_type(typeName);
+    }
 
-    function type_with_extended_attributes() {
+    function type_with_extended_attributes(typeName) {
       const extAttrs = extended_attrs();
-      const ret = single_type() || union_type();
+      const ret = single_type(typeName) || union_type(typeName);
       if (extAttrs.length && ret) ret.extAttrs = extAttrs;
       return ret;
-    };
+    }
 
     function argument(store) {
       const ret = { optional: false, variadic: false };
       ret.extAttrs = extended_attrs(store);
       all_ws(store, "pea");
       const opt_token = consume(ID, "optional");
       if (opt_token) {
         ret.optional = true;
         all_ws();
       }
-      ret.idlType = type_with_extended_attributes();
+      ret.idlType = type_with_extended_attributes("argument-type");
       if (!ret.idlType) {
         if (opt_token) tokens.unshift(opt_token);
         return;
       }
       const type_token = last_token;
       if (!ret.optional) {
         all_ws();
         if (tokens.length >= 3 &&
@@ -317,30 +387,30 @@
       if (ret.optional) {
         all_ws();
         const dflt = default_();
         if (typeof dflt !== "undefined") {
           ret["default"] = dflt;
         }
       }
       return ret;
-    };
+    }
 
     function argument_list(store) {
       const ret = [];
       const arg = argument(store ? ret : null);
       if (!arg) return;
       ret.push(arg);
       while (true) {
         all_ws(store ? ret : null);
         if (!consume(OTHER, ",")) return ret;
         const nxt = argument(store ? ret : null) || error("Trailing comma in arguments list");
         ret.push(nxt);
       }
-    };
+    }
 
     function simple_extended_attr(store) {
       all_ws();
       const name = consume(ID);
       if (!name) return;
       const ret = {
         name: name.value,
         "arguments": null,
@@ -381,17 +451,17 @@
         // [Constructor()]
         else {
           ret["arguments"] = [];
         }
         all_ws();
         consume(OTHER, ")") || error("Unexpected token in extended attribute argument list");
       }
       return ret;
-    };
+    }
 
     // Note: we parse something simpler than the official syntax. It's all that ever
     // seems to be used
     function extended_attrs(store) {
       const eas = [];
       all_ws(store);
       if (!consume(OTHER, "[")) return eas;
       eas[0] = simple_extended_attr(store) || error("Extended attribute with not content");
@@ -401,173 +471,172 @@
           eas.push(simple_extended_attr(store));
         } else {
           eas.push(simple_extended_attr(store) || error("Trailing comma in extended attribute"));
         }
       }
       all_ws();
       consume(OTHER, "]") || error("No end of extended attribute");
       return eas;
-    };
+    }
 
     function default_() {
       all_ws();
       if (consume(OTHER, "=")) {
         all_ws();
         const 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 {
           const str = consume(STR) || error("No value for default");
-          str.value = str.value.replace(/^"/, "").replace(/"$/, "");
+          str.value = str.value.slice(1, -1);
           return str;
         }
       }
-    };
+    }
 
     function const_(store) {
       all_ws(store, "pea");
       if (!consume(ID, "const")) return;
       const ret = { type: "const", nullable: false };
       all_ws();
       let typ = primitive_type();
       if (!typ) {
         typ = consume(ID) || error("No type for const");
         typ = typ.value;
       }
-      ret.idlType = typ;
+      ret.idlType = { type: "const-type", idlType: typ };
       all_ws();
       if (consume(OTHER, "?")) {
         ret.nullable = true;
         all_ws();
       }
       const name = consume(ID) || error("No name for const");
       ret.name = name.value;
       all_ws();
       consume(OTHER, "=") || error("No value assignment for const");
       all_ws();
       const cnt = const_value();
       if (cnt) ret.value = cnt;
       else error("No value for const");
       all_ws();
       consume(OTHER, ";") || error("Unterminated const");
       return ret;
-    };
+    }
 
     function inheritance() {
       all_ws();
       if (consume(OTHER, ":")) {
         all_ws();
         const inh = consume(ID) || error("No type in inheritance");
         return inh.value;
       }
-    };
+    }
 
     function operation_rest(ret, store) {
       all_ws();
       if (!ret) ret = {};
       const 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;
-    };
+    }
 
     function callback(store) {
       all_ws(store, "pea");
       let ret;
       if (!consume(ID, "callback")) return;
       all_ws();
       const tok = consume(ID, "interface");
       if (tok) {
-        ret = interface_rest();
-        ret.type = "callback interface";
+        ret = interface_rest(false, store, "callback interface");
         return ret;
       }
       const name = consume(ID) || error("No name for callback");
-      ret = { type: "callback", name: sanitize_name(name.value, "callback") };
+      ret = current = { type: "callback", name: sanitize_name(name.value, "callback") };
       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;
-    };
+    }
 
     function attribute(store) {
       all_ws(store, "pea");
       const grabbed = [];
       const ret = {
         type: "attribute",
-        "static": false,
+        static: false,
         stringifier: false,
         inherit: false,
         readonly: false
       };
       const 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");
+        if (ret.static || ret.stringifier) error("Cannot have a static or stringifier inherit");
         ret.inherit = true;
         grabbed.push(last_token);
         const w = all_ws();
         if (w) grabbed.push(w);
       }
       if (consume(ID, "readonly")) {
         ret.readonly = true;
         grabbed.push(last_token);
         const w = all_ws();
         if (w) grabbed.push(w);
       }
       const rest = attribute_rest(ret);
       if (!rest) {
         tokens = grabbed.concat(tokens);
       }
       return rest;
-    };
+    }
 
     function attribute_rest(ret) {
       if (!consume(ID, "attribute")) {
         return;
       }
       all_ws();
-      ret.idlType = type_with_extended_attributes() || error("No type in attribute");
+      ret.idlType = type_with_extended_attributes("attribute-type") || error("No type in attribute");
       if (ret.idlType.sequence) error("Attributes cannot accept sequence types");
       if (ret.idlType.generic === "record") error("Attributes cannot accept record types");
       all_ws();
       const name = consume(ID) || error("No name in attribute");
       ret.name = name.value;
       all_ws();
       consume(OTHER, ";") || error("Unterminated attribute");
       return ret;
-    };
+    }
 
     function return_type() {
-      const typ = type();
+      const typ = type("return-type");
       if (!typ) {
         if (consume(ID, "void")) {
           return "void";
         } else error("No return type");
       }
       return typ;
-    };
+    }
 
     function operation(store) {
       all_ws(store, "pea");
       const ret = Object.assign({}, EMPTY_OPERATION);
       while (true) {
         all_ws();
         if (consume(ID, "getter")) ret.getter = true;
         else if (consume(ID, "setter")) ret.setter = true;
@@ -577,34 +646,19 @@
       if (ret.getter || ret.setter || ret.deleter) {
         all_ws();
         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;
-      }
-    };
+      operation_rest(ret, store);
+      return ret;
+    }
 
     function static_member(store) {
       all_ws(store, "pea");
       if (!consume(ID, "static")) return;
       all_ws();
       return noninherited_attribute(store, "static") ||
         regular_operation(store, "static") ||
         error("No body in static member");
@@ -626,31 +680,31 @@
       while (true) {
         all_ws();
         if (consume(OTHER, ",")) {
           all_ws();
           const name = consume(ID) || error("Trailing comma in identifiers list");
           arr.push(name.value);
         } else break;
       }
-    };
+    }
 
     function iterable_type() {
       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;
-    };
+    }
 
     function readonly_iterable_type() {
       if (consume(ID, "maplike")) return "maplike";
       else if (consume(ID, "setlike")) return "setlike";
       else return;
-    };
+    }
 
     function iterable(store) {
       all_ws(store, "pea");
       const grabbed = [];
       const ret = { type: null, idlType: null, readonly: false };
       if (consume(ID, "readonly")) {
         ret.readonly = true;
         grabbed.push(last_token);
@@ -667,47 +721,44 @@
 
       const secondTypeRequired = ittype === "maplike";
       const 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_with_extended_attributes() || error(`Error parsing ${ittype} declaration`);
+        ret.idlType = [type_with_extended_attributes()] || error(`Error parsing ${ittype} declaration`);
         all_ws();
         if (secondTypeAllowed) {
-          let type2 = null;
           if (consume(OTHER, ",")) {
             all_ws();
-            type2 = type_with_extended_attributes();
+            ret.idlType.push(type_with_extended_attributes());
             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;
-    };
+    }
 
-    function interface_rest(isPartial, store) {
+    function interface_rest(isPartial, store, typeName = "interface") {
       all_ws();
       const name = consume(ID) || error("No name for interface");
       const mems = [];
-      const ret = {
-        type: "interface",
+      const ret = current = {
+        type: typeName,
         name: isPartial ? name.value : sanitize_name(name.value, "interface"),
-        partial: false,
+        partial: isPartial,
         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, "}")) {
@@ -728,28 +779,28 @@
           stringifier(store ? mems : null) ||
           iterable(store ? mems : null) ||
           attribute(store ? mems : null) ||
           operation(store ? mems : null) ||
           error("Unknown member");
         mem.extAttrs = ea;
         ret.members.push(mem);
       }
-    };
+    }
 
     function mixin_rest(isPartial, store) {
       all_ws();
       if (!consume(ID, "mixin")) return;
       all_ws();
       const name = consume(ID) || error("No name for interface mixin");
       const mems = [];
-      const ret = {
+      const ret = current = {
         type: "interface mixin",
         name: isPartial ? name.value : sanitize_name(name.value, "interface mixin"),
-        partial: false,
+        partial: isPartial,
         members: mems
       };
       all_ws();
       consume(OTHER, "{") || error("Bodyless interface mixin");
       while (true) {
         all_ws(store ? mems : null);
         if (consume(OTHER, "}")) {
           all_ws();
@@ -782,17 +833,17 @@
     }
 
     function namespace(isPartial, store) {
       all_ws(isPartial ? null : store, "pea");
       if (!consume(ID, "namespace")) return;
       all_ws();
       const name = consume(ID) || error("No name for namespace");
       const mems = [];
-      const ret = {
+      const ret = current = {
         type: "namespace",
         name: isPartial ? name.value : sanitize_name(name.value, "namespace"),
         partial: isPartial,
         members: mems
       };
       all_ws();
       consume(OTHER, "{") || error("Bodyless namespace");
       while (true) {
@@ -812,17 +863,17 @@
       }
     }
 
     function noninherited_attribute(store, prefix) {
       const w = all_ws(store, "pea");
       const grabbed = [];
       const ret = {
         type: "attribute",
-        "static": false,
+        static: false,
         stringifier: false,
         inherit: false,
         readonly: false
       };
       if (prefix) {
         ret[prefix] = true;
       }
       if (w) grabbed.push(w);
@@ -851,46 +902,45 @@
 
     function partial(store) {
       all_ws(store, "pea");
       if (!consume(ID, "partial")) return;
       const thing = dictionary(true, store) ||
         interface_(true, store) ||
         namespace(true, store) ||
         error("Partial doesn't apply to anything");
-      thing.partial = true;
       return thing;
-    };
+    }
 
     function dictionary(isPartial, store) {
       all_ws(isPartial ? null : store, "pea");
       if (!consume(ID, "dictionary")) return;
       all_ws();
       const name = consume(ID) || error("No name for dictionary");
       const mems = [];
-      const ret = {
+      const ret = current = {
         type: "dictionary",
         name: isPartial ? name.value : sanitize_name(name.value, "dictionary"),
-        partial: false,
+        partial: isPartial,
         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;
         }
         const ea = extended_attrs(store ? mems : null);
         all_ws(store ? mems : null, "pea");
         const required = consume(ID, "required");
-        const typ = type_with_extended_attributes() || error("No type for dictionary member");
+        const typ = type_with_extended_attributes("dictionary-type") || error("No type for dictionary member");
         all_ws();
         const name = consume(ID) || error("No name for dictionary member");
         const dflt = default_();
         if (required && dflt) error("Required member must not have a default");
         const member = {
           type: "field",
           name: name.value,
           required: !!required,
@@ -899,68 +949,69 @@
         };
         if (typeof dflt !== "undefined") {
           member["default"] = dflt;
         }
         ret.members.push(member);
         all_ws();
         consume(OTHER, ";") || error("Unterminated dictionary member");
       }
-    };
+    }
 
     function enum_(store) {
       all_ws(store, "pea");
       if (!consume(ID, "enum")) return;
       all_ws();
       const name = consume(ID) || error("No name for enum");
       const vals = [];
-      const ret = {
+      const ret = current = {
         type: "enum",
         name: sanitize_name(name.value, "enum"),
         values: vals
       };
       all_ws();
       consume(OTHER, "{") || error("No curly for enum");
       let saw_comma = false;
       while (true) {
         all_ws(store ? vals : null);
         if (consume(OTHER, "}")) {
           all_ws();
           consume(OTHER, ";") || error("No semicolon after enum");
           return ret;
         }
         const val = consume(STR) || error("Unexpected value in enum");
-        val.value = val.value.replace(/"/g, "");
+        val.value = val.value.slice(1, -1);
         ret.values.push(val);
         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;
         }
       }
-    };
+    }
 
     function typedef(store) {
       all_ws(store, "pea");
       if (!consume(ID, "typedef")) return;
       const ret = {
         type: "typedef"
       };
       all_ws();
-      ret.idlType = type_with_extended_attributes() || error("No type in typedef");
+      ret.idlType = type_with_extended_attributes("typedef-type") || error("No type in typedef");
       all_ws();
       const name = consume(ID) || error("No name in typedef");
       ret.name = sanitize_name(name.value, "typedef");
+      current = ret;
       all_ws();
       consume(OTHER, ";") || error("Unterminated typedef");
       return ret;
-    };
+    }
 
     function implements_(store) {
       all_ws(store, "pea");
       const target = consume(ID);
       if (!target) return;
       const w = all_ws();
       if (consume(ID, "implements")) {
         const ret = {
@@ -973,17 +1024,17 @@
         all_ws();
         consume(OTHER, ";") || error("No terminating ; for implements statement");
         return ret;
       } else {
         // rollback
         tokens.unshift(w);
         tokens.unshift(target);
       }
-    };
+    }
 
     function includes(store) {
       all_ws(store, "pea");
       const target = consume(ID);
       if (!target) return;
       const w = all_ws();
       if (consume(ID, "includes")) {
         const ret = {
@@ -996,49 +1047,49 @@
         all_ws();
         consume(OTHER, ";") || error("No terminating ; for includes statement");
         return ret;
       } else {
         // rollback
         tokens.unshift(w);
         tokens.unshift(target);
       }
-    };
+    }
 
     function definition(store) {
       return callback(store) ||
         interface_(false, store) ||
         partial(store) ||
         dictionary(false, store) ||
         enum_(store) ||
         typedef(store) ||
         implements_(store) ||
         includes(store) ||
         namespace(false, store);
-    };
+    }
 
     function definitions(store) {
       if (!tokens.length) return [];
       const defs = [];
       while (true) {
         const ea = extended_attrs(store ? defs : null);
         const def = definition(store ? defs : null);
         if (!def) {
           if (ea.length) error("Stray extended attributes");
           break;
         }
         def.extAttrs = ea;
         defs.push(def);
       }
       return defs;
-    };
+    }
     const res = definitions(opt.ws);
     if (tokens.length) error("Unrecognised tokens");
     return res;
-  };
+  }
 
   const obj = {
     parse(str, opt) {
       if (!opt) opt = {};
       const tokens = tokenise(str);
       return parse(tokens, opt);
     }
   };
--- a/testing/web-platform/tests/resources/webidl2/lib/writer.js
+++ b/testing/web-platform/tests/resources/webidl2/lib/writer.js
@@ -1,264 +1,273 @@
-(function() {
+"use strict";
 
-  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];
+(() => {
+  function write(ast, opt = {}) {
+    let curPea = "";
+    let curTPea = "";
+    const noop = str => str;
+    const optNames = "type".split(" ");
+    const context = [];
+    for (const o of optNames) {
       if (!opt[o]) opt[o] = noop;
     }
 
-    var literal = function(it) {
+    function literal(it) {
       return it.value;
     };
-    var wsPea = function(it) {
+    function wsPea(it) {
       curPea += it.value;
       return "";
     };
-    var wsTPea = function(it) {
+    function wsTPea(it) {
       curTPea += it.value;
       return "";
     };
-    var lineComment = function(it) {
-      return "//" + it.value + "\n";
+    function lineComment(it) {
+      return `//${it.value}\n`;
     };
-    var multilineComment = function(it) {
-      return "/*" + it.value + "*/";
+    function multilineComment(it) {
+      return `/*${it.value}*/`;
     };
-    var type = function(it) {
+    function type(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.generic) ret += it.generic + "<";
-      else if (it.sequence) ret += "sequence<";
-      if (Array.isArray(it.idlType)) ret += it.idlType.map(type).join(", ");
-      else ret += type(it.idlType);
-      if (it.array || it.generic === 'Array') {
-        for (var i = 0, n = it.nullableArray.length; i < n; i++) {
-          var val = it.nullableArray[i];
-          if (val) ret += "?";
-          ret += "[]";
-        }
+      let ret = extended_attributes(it.extAttrs, curPea);
+      if (it.union) ret += `(${it.idlType.map(type).join(" or ")})`;
+      else {
+        if (it.generic) ret += `${it.generic}<`;
+        if (Array.isArray(it.idlType)) ret += it.idlType.map(type).join(", ");
+        else ret += type(it.idlType);
+        if (it.generic) ret += ">";
       }
-      if (it.generic || it.sequence) ret += ">";
       if (it.nullable) ret += "?";
 
       return ret;
     };
-    var const_value = function(it) {
-      var tp = it.type;
+    function const_value(it) {
+      const 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 + '"';
+      else if (tp === "sequence") return "[]";
+      else return `"${it.value}"`;
     };
-    var argument = function(arg, pea) {
-      var ret = extended_attributes(arg.extAttrs, pea);
+    function argument(arg, pea) {
+      let 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"]);
+      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];
+    function args(its) {
+      let res = "";
+      let pea = "";
+      for (let i = 0, n = its.length; i < n; i++) {
+        const 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;
+    function make_ext_at(it) {
       context.unshift(it);
-      var ret = it.name + "(" + (it["arguments"].length ? args(it["arguments"]) : "") + ")";
+      let ret = it.name;
+      if (it.rhs) {
+        if (it.rhs.type === "identifier-list") ret += `=(${it.rhs.value.join(',')})`;
+        else ret += `=${it.rhs.value}`;
+      }
+      if (it.arguments) ret += `(${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) {
+    function extended_attributes(eats, pea) {
       if (!eats || !eats.length) return "";
-      return "[" + eats.map(make_ext_at).join(", ") + "]" + pea;
+      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);
+    const modifiers = "getter setter creator deleter legacycaller stringifier static".split(" ");
+    function operation(it) {
+      let 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];
+      for (const mod of modifiers) {
         if (it[mod]) ret += mod + " ";
       }
       ret += type(it.idlType) + " ";
       if (it.name) ret += it.name;
-      ret += "(" + args(it["arguments"]) + ");";
+      ret += `(${args(it["arguments"])});`;
       return ret;
     };
 
-    var attribute = function(it) {
-      var ret = extended_attributes(it.extAttrs, curPea);
+    function attribute(it) {
+      let 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 + ";";
+      ret += `attribute ${type(it.idlType)} ${it.name};`;
       return ret;
     };
 
-    var interface_ = function(it) {
-      var ret = extended_attributes(it.extAttrs, curPea);
+    function interface_(it) {
+      let 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) + "};";
+      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);
+    function interface_mixin(it) {
+      let ret = extended_attributes(it.extAttrs, curPea);
+      curPea = "";
+      if (it.partial) ret += "partial ";
+      ret += `interface mixin ${it.name} `;
+      ret += `{${iterate(it.members)}};`;
+      return ret;
+    }
+
+    function namespace(it) {
+      let ret = extended_attributes(it.extAttrs, curPea);
       curPea = "";
       if (it.partial) ret += "partial ";
-      ret += "dictionary " + it.name + " ";
-      ret += "{" + iterate(it.members) + "};";
+      ret += `namespace ${it.name} `;
+      ret += `{${iterate(it.members)}};`;
+      return ret;
+    }
+
+    function dictionary(it) {
+      let ret = extended_attributes(it.extAttrs, curPea);
+      curPea = "";
+      if (it.partial) ret += "partial ";
+      ret += `dictionary ${it.name} `;
+      if (it.inheritance) ret += `: ${it.inheritance} `;
+      ret += `{${iterate(it.members)}};`;
       return ret;
     };
-    var field = function(it) {
-      var ret = extended_attributes(it.extAttrs, curPea);
+    function field(it) {
+      let ret = extended_attributes(it.extAttrs, curPea);
       curPea = "";
       if (it.required) ret += "required ";
-      ret += type(it.idlType) + " " + it.name;
-      if (it["default"]) ret += " = " + const_value(it["default"]);
+      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);
+    function const_(it) {
+      const ret = extended_attributes(it.extAttrs, curPea);
       curPea = "";
-      ret += "exception " + it.name + " ";
-      if (it.inheritance) ret += ": " + it.inheritance + " ";
-      ret += "{" + iterate(it.members) + "};";
-      return ret;
+      return `${ret}const ${type(it.idlType)}${it.nullable ? "?" : ""} ${it.name} = ${const_value(it.value)};`;
     };
-    var const_ = function(it) {
-      var ret = extended_attributes(it.extAttrs, curPea);
+    function typedef(it) {
+      let 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);
+      ret += `typedef ${extended_attributes(it.typeExtAttrs, curTPea)}`;
       curTPea = "";
-      return ret + type(it.idlType) + " " + it.name + ";";
+      return `${ret}${type(it.idlType)} ${it.name};`;
     };
-    var implements_ = function(it) {
-      var ret = extended_attributes(it.extAttrs, curPea);
+    function implements_(it) {
+      const ret = extended_attributes(it.extAttrs, curPea);
       curPea = "";
-      return ret + it.target + " implements " + it["implements"] + ";";
+      return `${ret}${it.target} implements ${it["implements"]};`;
     };
-    var callback = function(it) {
-      var ret = extended_attributes(it.extAttrs, curPea);
+    function includes(it) {
+      const ret = extended_attributes(it.extAttrs, curPea);
       curPea = "";
-      return ret + "callback " + it.name + " = " + type(it.idlType) +
-        "(" + args(it["arguments"]) + ");";
+      return `${ret}${it.target} includes ${it.includes};`;
+    };
+    function callback(it) {
+      const 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);
+    function enum_(it) {
+      let 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 + '"';
+      ret += `enum ${it.name} {`;
+      for (const v of it.values) {
+        if (v.type === "string") ret += `"${v.value}"`;
         else if (v.type === "ws") ret += v.value;
         else if (v.type === ",") ret += ",";
       }
       return ret + "};";
     };
-    var iterable = function(it) {
-      return "iterable<" + (it.idlType instanceof Array ? it.idlType.map(type).join(", ") : type(it.idlType)) + ">;";
+    function iterable(it) {
+      return `iterable<${Array.isArray(it.idlType) ? it.idlType.map(type).join(", ") : type(it.idlType)}>;`;
     };
-    var legacyiterable = function(it) {
-      return "legacyiterable<" + (it.idlType instanceof Array ? it.idlType.map(type).join(", ") : type(it.idlType)) + ">;";
+    function legacyiterable(it) {
+      return `legacyiterable<${Array.isArray(it.idlType) ? it.idlType.map(type).join(", ") : type(it.idlType)}>;`;
     };
-    var maplike = function(it) {
-      return (it.readonly ? "readonly " : "") + "maplike<" +
-        it.idlType.map(type).join(", ") + ">;";
+    function maplike(it) {
+      return `${it.readonly ? "readonly " : ""}maplike<${it.idlType.map(type).join(", ")}>;`;
     };
-    var setlike = function(it) {
-      return (it.readonly ? "readonly " : "") + "setlike<" +
-        type(it.idlType) + ">;";
+    function setlike(it) {
+      return `${it.readonly ? "readonly " : ""}setlike<${type(it.idlType[0])}>;`;
     };
-    var callbackInterface = function(it) {
-      return 'callback ' + interface_(it);
+    function callbackInterface(it) {
+      return `callback ${interface_(it)}`;
     };
 
-    var table = {
+    const 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_,
-      iterable: iterable,
-      legacyiterable: legacyiterable,
-      maplike: maplike,
-      setlike: setlike,
+      interface: interface_,
+      "interface mixin": interface_mixin,
+      namespace,
+      operation,
+      attribute,
+      dictionary,
+      field,
+      const: const_,
+      typedef,
+      implements: implements_,
+      includes,
+      callback,
+      enum: enum_,
+      iterable,
+      legacyiterable,
+      maplike,
+      setlike,
       "callback interface": callbackInterface
     };
-    var dispatch = function(it) {
+    function dispatch(it) {
+      const dispatcher = table[it.type];
+      if (!dispatcher) {
+        throw new Error(`Type "${it.type}" is unsupported`)
+      }
       return table[it.type](it);
     };
-    var iterate = function(things) {
+    function iterate(things) {
       if (!things) return;
-      var ret = "";
-      for (var i = 0, n = things.length; i < n; i++) ret += dispatch(things[i]);
+      let ret = "";
+      for (const thing of things) ret += dispatch(thing);
       return ret;
     };
     return iterate(ast);
   };
 
 
-  var obj = {
-    write: function(ast, opt) {
-      if (!opt) opt = {};
-      return write(ast, opt);
-    }
+  const obj = {
+    write
   };
 
   if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
     module.exports = obj;
   } else if (typeof define === 'function' && define.amd) {
-    define([], function() {
-      return obj;
-    });
+    define([], () => obj);
   } else {
     (self || window).WebIDL2Writer = obj;
   }
-}());
+})();
--- a/testing/web-platform/tests/resources/webidl2/package-lock.json
+++ b/testing/web-platform/tests/resources/webidl2/package-lock.json
@@ -1,30 +1,57 @@
 {
   "name": "webidl2",
-  "version": "4.2.0",
+  "version": "10.2.1",
   "lockfileVersion": 1,
+  "requires": true,
   "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.40.tgz",
+      "integrity": "sha512-eVXQSbu/RimU6OKcK2/gDJVTFcxXJI4sHbIqw2mhwMZeQ2as/8AhS9DGkEDoHMBBNJZ5B0US63lF56x+KDcxiA==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "7.0.0-beta.40"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.0.0-beta.40",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.40.tgz",
+      "integrity": "sha512-mOhhTrzieV6VO7odgzFGFapiwRK0ei8RZRhfzHhb6cpX3QM8XXuCLXWjN8qBB7JReDdUR80V3LFfFrGUYevhNg==",
+      "dev": true,
+      "requires": {
+        "chalk": "2.3.2",
+        "esutils": "2.0.2",
+        "js-tokens": "3.0.2"
+      }
+    },
     "ansi-regex": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
-      "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
       "dev": true
     },
     "ansi-styles": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
-      "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=",
-      "dev": true
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "1.9.1"
+      }
     },
     "arr-diff": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
       "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "arr-flatten": "1.1.0"
+      }
     },
     "arr-flatten": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
       "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
       "dev": true
     },
     "array-unique": {
@@ -35,214 +62,281 @@
     },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
       "dev": true
     },
     "brace-expansion": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
-      "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
-      "dev": true
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "1.0.0",
+        "concat-map": "0.0.1"
+      }
     },
     "braces": {
       "version": "1.8.5",
       "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
       "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "expand-range": "1.8.2",
+        "preserve": "0.2.0",
+        "repeat-element": "1.1.2"
+      }
     },
     "browser-stdout": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
-      "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+      "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
       "dev": true
     },
     "chalk": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
-      "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
-      "dev": true
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
+      "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "3.2.1",
+        "escape-string-regexp": "1.0.5",
+        "supports-color": "5.3.0"
+      }
     },
     "color-convert": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz",
-      "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=",
-      "dev": true
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+      "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
     },
     "color-name": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
       "dev": true
     },
     "commander": {
-      "version": "2.9.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
-      "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+      "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
       "dev": true
     },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "dev": true
     },
     "debug": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz",
-      "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+      "dev": true,
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "diff": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
       "dev": true
     },
-    "diff": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
-      "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
+    "diff-match-patch": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz",
+      "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg=",
       "dev": true
     },
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+      "dev": true
+    },
     "expand-brackets": {
       "version": "0.1.5",
       "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
       "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-posix-bracket": "0.1.1"
+      }
     },
     "expand-range": {
       "version": "1.8.2",
       "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
       "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "fill-range": "2.2.3"
+      }
     },
     "expect": {
-      "version": "21.2.1",
-      "resolved": "https://registry.npmjs.org/expect/-/expect-21.2.1.tgz",
-      "integrity": "sha512-orfQQqFRTX0jH7znRIGi8ZMR8kTNpXklTTz8+HGTpmTKZo3Occ6JNB5FXMb8cRuiiC/GyDqsr30zUa66ACYlYw==",
+      "version": "22.4.0",
+      "resolved": "https://registry.npmjs.org/expect/-/expect-22.4.0.tgz",
+      "integrity": "sha512-Fiy862jT3qc70hwIHwwCBNISmaqBrfWKKrtqyMJ6iwZr+6KXtcnHojZFtd63TPRvRl8EQTJ+YXYy2lK6/6u+Hw==",
       "dev": true,
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
-          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
-          "dev": true
-        }
+      "requires": {
+        "ansi-styles": "3.2.1",
+        "jest-diff": "22.4.0",
+        "jest-get-type": "22.1.0",
+        "jest-matcher-utils": "22.4.0",
+        "jest-message-util": "22.4.0",
+        "jest-regex-util": "22.1.0"
       }
     },
     "extglob": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
       "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-extglob": "1.0.0"
+      }
     },
     "filename-regex": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
       "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
       "dev": true
     },
     "fill-range": {
       "version": "2.2.3",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
       "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-number": "2.1.0",
+        "isobject": "2.1.0",
+        "randomatic": "1.1.7",
+        "repeat-element": "1.1.2",
+        "repeat-string": "1.6.1"
+      }
     },
     "for-in": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
       "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
       "dev": true
     },
     "for-own": {
       "version": "0.1.5",
       "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
       "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "for-in": "1.0.2"
+      }
     },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
       "dev": true
     },
     "glob": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
-      "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
-      "dev": true
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "1.0.0",
+        "inflight": "1.0.6",
+        "inherits": "2.0.3",
+        "minimatch": "3.0.4",
+        "once": "1.4.0",
+        "path-is-absolute": "1.0.1"
+      }
     },
     "glob-base": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
       "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "glob-parent": "2.0.0",
+        "is-glob": "2.0.1"
+      }
     },
     "glob-parent": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
       "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
-      "dev": true
-    },
-    "graceful-readlink": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
-      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-glob": "2.0.1"
+      }
     },
     "growl": {
-      "version": "1.9.2",
-      "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
-      "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
-      "dev": true
-    },
-    "has-ansi": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
-      "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
+      "version": "1.10.3",
+      "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
+      "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
       "dev": true
     },
     "has-flag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
-      "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
+    },
+    "he": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+      "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
       "dev": true
     },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "once": "1.4.0",
+        "wrappy": "1.0.2"
+      }
     },
     "inherits": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
       "dev": true
     },
     "is-buffer": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
-      "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
       "dev": true
     },
     "is-dotfile": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
       "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
       "dev": true
     },
     "is-equal-shallow": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
       "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-primitive": "2.0.0"
+      }
     },
     "is-extendable": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
       "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
       "dev": true
     },
     "is-extglob": {
@@ -250,23 +344,29 @@
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
       "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
       "dev": true
     },
     "is-glob": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
       "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-extglob": "1.0.0"
+      }
     },
     "is-number": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
       "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "kind-of": "3.2.2"
+      }
     },
     "is-posix-bracket": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
       "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
       "dev": true
     },
     "is-primitive": {
@@ -280,331 +380,291 @@
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
       "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
       "dev": true
     },
     "isobject": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
       "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "isarray": "1.0.0"
+      }
     },
     "jest-diff": {
-      "version": "21.2.1",
-      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-21.2.1.tgz",
-      "integrity": "sha512-E5fu6r7PvvPr5qAWE1RaUwIh/k6Zx/3OOkZ4rk5dBJkEWRrUuSgbMt2EO8IUTPTd6DOqU3LW6uTIwX5FRvXoFA==",
+      "version": "22.4.0",
+      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-22.4.0.tgz",
+      "integrity": "sha512-+/t20WmnkOkB8MOaGaPziI8zWKxquMvYw4Ub+wOzi7AUhmpFXz43buWSxVoZo4J5RnCozpGbX3/FssjJ5KV9Nw==",
       "dev": true,
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
-          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
-          "dev": true
-        },
-        "chalk": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
-          "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
-          "dev": true
-        },
-        "has-flag": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "4.4.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
-          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
-          "dev": true
-        }
+      "requires": {
+        "chalk": "2.3.2",
+        "diff": "3.5.0",
+        "jest-get-type": "22.1.0",
+        "pretty-format": "22.4.0"
       }
     },
     "jest-get-type": {
-      "version": "21.2.0",
-      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-21.2.0.tgz",
-      "integrity": "sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q==",
+      "version": "22.1.0",
+      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.1.0.tgz",
+      "integrity": "sha512-nD97IVOlNP6fjIN5i7j5XRH+hFsHL7VlauBbzRvueaaUe70uohrkz7pL/N8lx/IAwZRTJ//wOdVgh85OgM7g3w==",
       "dev": true
     },
     "jest-matcher-utils": {
-      "version": "21.2.1",
-      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-21.2.1.tgz",
-      "integrity": "sha512-kn56My+sekD43dwQPrXBl9Zn9tAqwoy25xxe7/iY4u+mG8P3ALj5IK7MLHZ4Mi3xW7uWVCjGY8cm4PqgbsqMCg==",
+      "version": "22.4.0",
+      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-22.4.0.tgz",
+      "integrity": "sha512-03m3issxUXpWMwDYTfmL8hRNewUB0yCRTeXPm+eq058rZxLHD9f5NtSSO98CWHqe4UyISIxd9Ao9iDVjHWd2qg==",
       "dev": true,
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
-          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
-          "dev": true
-        },
-        "chalk": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
-          "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
-          "dev": true
-        },
-        "has-flag": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "4.4.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
-          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
-          "dev": true
-        }
+      "requires": {
+        "chalk": "2.3.2",
+        "jest-get-type": "22.1.0",
+        "pretty-format": "22.4.0"
       }
     },
     "jest-message-util": {
-      "version": "21.2.1",
-      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-21.2.1.tgz",
-      "integrity": "sha512-EbC1X2n0t9IdeMECJn2BOg7buOGivCvVNjqKMXTzQOu7uIfLml+keUfCALDh8o4rbtndIeyGU8/BKfoTr/LVDQ==",
+      "version": "22.4.0",
+      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-22.4.0.tgz",
+      "integrity": "sha512-eyCJB0T3hrlpFF2FqQoIB093OulP+1qvATQmD3IOgJgMGqPL6eYw8TbC5P/VCWPqKhGL51xvjIIhow5eZ2wHFw==",
       "dev": true,
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
-          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
-          "dev": true
-        },
-        "chalk": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
-          "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
-          "dev": true
-        },
-        "has-flag": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "4.4.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
-          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
-          "dev": true
-        }
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.40",
+        "chalk": "2.3.2",
+        "micromatch": "2.3.11",
+        "slash": "1.0.0",
+        "stack-utils": "1.0.1"
       }
     },
     "jest-regex-util": {
-      "version": "21.2.0",
-      "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-21.2.0.tgz",
-      "integrity": "sha512-BKQ1F83EQy0d9Jen/mcVX7D+lUt2tthhK/2gDWRgLDJRNOdRgSp1iVqFxP8EN1ARuypvDflRfPzYT8fQnoBQFQ==",
+      "version": "22.1.0",
+      "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-22.1.0.tgz",
+      "integrity": "sha512-on0LqVS6Xeh69sw3d1RukVnur+lVOl3zkmb0Q54FHj9wHoq6dbtWqb3TSlnVUyx36hqjJhjgs/QLqs07Bzu72Q==",
       "dev": true
     },
-    "json3": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
-      "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+    "js-tokens": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
       "dev": true
     },
     "jsondiffpatch": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.2.4.tgz",
-      "integrity": "sha1-1LbFOz/H2htLkcHCrsi5MrdRHVw=",
-      "dev": true
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.3.5.tgz",
+      "integrity": "sha512-v7eaGLDMCHXH+fsIaZhptEUJmS8EJpunq7IM4cc4vIT/kSRAkaZ6ZF4ebiNcyUelL0znbvj6o2B5Gh9v7Og0BQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "2.3.2",
+        "diff-match-patch": "1.0.0"
+      }
     },
     "kind-of": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
       "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-      "dev": true
-    },
-    "lodash._baseassign": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
-      "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
-      "dev": true
-    },
-    "lodash._basecopy": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
-      "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
-      "dev": true
-    },
-    "lodash._basecreate": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
-      "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
-      "dev": true
-    },
-    "lodash._getnative": {
-      "version": "3.9.1",
-      "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
-      "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
-      "dev": true
-    },
-    "lodash._isiterateecall": {
-      "version": "3.0.9",
-      "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
-      "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
-      "dev": true
-    },
-    "lodash.create": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
-      "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
-      "dev": true
-    },
-    "lodash.isarguments": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
-      "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
-      "dev": true
-    },
-    "lodash.isarray": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
-      "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
-      "dev": true
-    },
-    "lodash.keys": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
-      "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-buffer": "1.1.6"
+      }
     },
     "micromatch": {
       "version": "2.3.11",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
       "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "arr-diff": "2.0.0",
+        "array-unique": "0.2.1",
+        "braces": "1.8.5",
+        "expand-brackets": "0.1.5",
+        "extglob": "0.3.2",
+        "filename-regex": "2.0.1",
+        "is-extglob": "1.0.0",
+        "is-glob": "2.0.1",
+        "kind-of": "3.2.2",
+        "normalize-path": "2.1.1",
+        "object.omit": "2.0.1",
+        "parse-glob": "3.0.4",
+        "regex-cache": "0.4.4"
+      }
     },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "brace-expansion": "1.1.11"
+      }
     },
     "minimist": {
       "version": "0.0.8",
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
       "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
       "dev": true
     },
     "mkdirp": {
       "version": "0.5.1",
       "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "minimist": "0.0.8"
+      }
     },
     "mocha": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.1.tgz",
-      "integrity": "sha1-o4ArSqOBk0yss43nDPdxYh2o+a8=",
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.0.4.tgz",
+      "integrity": "sha512-nMOpAPFosU1B4Ix1jdhx5e3q7XO55ic5a8cgYvW27CequcEY+BabS0kUVL1Cw1V5PuVHZWeNRWFLmEPexo79VA==",
       "dev": true,
+      "requires": {
+        "browser-stdout": "1.3.1",
+        "commander": "2.11.0",
+        "debug": "3.1.0",
+        "diff": "3.5.0",
+        "escape-string-regexp": "1.0.5",
+        "glob": "7.1.2",
+        "growl": "1.10.3",
+        "he": "1.1.1",
+        "mkdirp": "0.5.1",
+        "supports-color": "4.4.0"
+      },
       "dependencies": {
+        "has-flag": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+          "dev": true
+        },
         "supports-color": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
-          "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
-          "dev": true
+          "version": "4.4.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "2.0.0"
+          }
         }
       }
     },
     "ms": {
-      "version": "0.7.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
-      "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
       "dev": true
     },
     "normalize-path": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
       "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "remove-trailing-separator": "1.1.0"
+      }
     },
     "object.omit": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
       "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "for-own": "0.1.5",
+        "is-extendable": "0.1.1"
+      }
     },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "wrappy": "1.0.2"
+      }
     },
     "parse-glob": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
       "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "glob-base": "0.3.0",
+        "is-dotfile": "1.0.3",
+        "is-extglob": "1.0.0",
+        "is-glob": "2.0.1"
+      }
     },
     "path-is-absolute": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
       "dev": true
     },
     "preserve": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
       "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
       "dev": true
     },
     "pretty-format": {
-      "version": "21.2.1",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-21.2.1.tgz",
-      "integrity": "sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A==",
+      "version": "22.4.0",
+      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.0.tgz",
+      "integrity": "sha512-pvCxP2iODIIk9adXlo4S3GRj0BrJiil68kByAa1PrgG97c1tClh9dLMgp3Z6cHFZrclaABt0UH8PIhwHuFLqYA==",
       "dev": true,
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "ansi-styles": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
-          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
-          "dev": true
-        }
+      "requires": {
+        "ansi-regex": "3.0.0",
+        "ansi-styles": "3.2.1"
       }
     },
     "randomatic": {
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
       "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
       "dev": true,
+      "requires": {
+        "is-number": "3.0.0",
+        "kind-of": "4.0.0"
+      },
       "dependencies": {
         "is-number": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
           "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
           "dev": true,
+          "requires": {
+            "kind-of": "3.2.2"
+          },
           "dependencies": {
             "kind-of": {
               "version": "3.2.2",
               "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
               "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true
+              "dev": true,
+              "requires": {
+                "is-buffer": "1.1.6"
+              }
             }
           }
         },
         "kind-of": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
           "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
-          "dev": true
+          "dev": true,
+          "requires": {
+            "is-buffer": "1.1.6"
+          }
         }
       }
     },
     "regex-cache": {
       "version": "0.4.4",
       "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
       "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
-      "dev": true
+      "dev": true,
+      "requires": {
+        "is-equal-shallow": "0.1.3"
+      }
     },
     "remove-trailing-separator": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
       "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
       "dev": true
     },
     "repeat-element": {
@@ -620,27 +680,30 @@
       "dev": true
     },
     "slash": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
       "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
       "dev": true
     },
-    "strip-ansi": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
-      "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
+    "stack-utils": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz",
+      "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=",
       "dev": true
     },
     "supports-color": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
-      "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=",
-      "dev": true
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz",
+      "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==",
+      "dev": true,
+      "requires": {
+        "has-flag": "3.0.0"
+      }
     },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
     }
   }
--- a/testing/web-platform/tests/resources/webidl2/package.json
+++ b/testing/web-platform/tests/resources/webidl2/package.json
@@ -1,22 +1,24 @@
 {
   "name": "webidl2",
   "description": "A WebIDL Parser",
-  "version": "8.1.0",
+  "version": "10.2.1",
   "contributors": [
     "Robin Berjon <robin@berjon.com> (https://berjon.com)",
     "Marcos Caceres <marcos@marcosc.com> (https://marcosc.com)",
-    "Kagami Sascha Rosylight <saschaplas@outlook.com>"
+    "Kagami Sascha Rosylight <saschaplas@outlook.com>",
+    "Timothy Gu <timothygu99@gmail.com>"
   ],
   "license": "W3C",
   "dependencies": {},
   "devDependencies": {
-    "expect": "21.2.1",
-    "jsondiffpatch": "0.2.5",
-    "mocha": "4.0.1"
+    "expect": "22.4.0",
+    "jsondiffpatch": "0.3.5",
+    "mocha": "5.0.4"
   },
   "scripts": {
-    "test": "mocha"
+    "test": "mocha",
+    "acquire": "node test/util/acquire.js"
   },
-  "repository": "git://github.com/darobin/webidl2.js",
+  "repository": "git://github.com/w3c/webidl2.js",
   "main": "index"
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid.js
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid.js
@@ -1,40 +1,20 @@
 // NOTES:
 //  - the errors actually still need to be reviewed to check that they
 //    are fully correct interpretations of the IDLs
 
 "use strict";
 
-const wp = require("../lib/webidl2");
+const { collect } = require("./util/collect");
+const fs = require("fs");
 const expect = require("expect");
-const pth = require("path");
-const fs = require("fs");
 
 describe("Parses all of the invalid IDLs to check that they blow up correctly", () => {
-  const dir = pth.join(__dirname, "invalid/idl");
-  const skip = {};
-  const idls = fs.readdirSync(dir)
-    .filter(it => (/\.w?idl$/).test(it) && !skip[it])
-    .map(it => pth.join(dir, it));
-  const errors = idls.map(it => pth.join(__dirname, "invalid", "json", pth.basename(it).replace(/\.w?idl/, ".json")));
-
-  for (let i = 0, n = idls.length; i < n; i++) {
-    const idl = idls[i];
-    const err = JSON.parse(fs.readFileSync(errors[i], "utf8"));
-
-    it(`should produce the right error for ${idl}`, () => {
-      let error;
-      try {
-        var ast = wp.parse(fs.readFileSync(idl, "utf8"));
-        console.log(JSON.stringify(ast, null, 4));
-      }
-      catch (e) {
-        error = e;
-      }
-      finally {
-        expect(error).toBeTruthy();
-        expect(error.message).toEqual(err.message);
-        expect(error.line).toEqual(err.line);
-      }
+  for (const test of collect("invalid", { expectError: true })) {
+    it(`should produce the right error for ${test.path}`, () => {
+      const err = test.readJSON();
+      expect(test.error).toBeTruthy();
+      expect(test.error.message).toEqual(err.message);
+      expect(test.error.line).toEqual(err.line);
     });
   }
 });
rename from testing/web-platform/tests/resources/webidl2/test/syntax/idl/iterator.widl
rename to testing/web-platform/tests/resources/webidl2/test/invalid/idl/iterator.widl
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/no-semicolon-callback.widl
@@ -0,0 +1,7 @@
+callback interface NoSemicolon {
+  attribute boolean noSemiColon;
+}
+
+enum YouNeedOne {
+  "really"
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/no-semicolon.widl
@@ -0,0 +1,7 @@
+partial interface NoSemicolon {
+  attribute boolean noSemiColon;
+}
+
+enum YouNeedOne {
+  "really"
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/idl/stray-slash.widl
@@ -0,0 +1,2 @@
+// This is a comment.
+/ This is not.
rename from testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.idl
rename to testing/web-platform/tests/resources/webidl2/test/invalid/idl/stringconstants.widl
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/array.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/array.json
@@ -1,4 +1,4 @@
 {
-    "message": "No name in attribute",
+    "message": "Got an error during or right after parsing `interface LotteryResults`: No name in attribute",
     "line": 5
-}
\ No newline at end of file
+}
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/caller.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/caller.json
@@ -1,4 +1,4 @@
 {
-    "message": "Invalid operation",
+    "message": "Got an error during or right after parsing `interface NumberQuadrupler`: Invalid operation",
     "line": 6
 }
--- 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
@@ -1,4 +1,4 @@
 {
-    "message":  "Required member must not have a default"
+    "message":  "Got an error during or right after parsing `dictionary Dict`: Required member must not have a default"
 ,   "line":     4
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/duplicate.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/duplicate.json
@@ -1,4 +1,4 @@
 {
-    "message": "The name \"Test\" of type \"typedef\" is already seen",
+    "message": "Got an error during or right after parsing `typedef Test`: The name \"Test\" of type \"typedef\" is already seen",
     "line": 3
-}
\ No newline at end of file
+}
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/enum.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/enum.json
@@ -1,4 +1,4 @@
 {
-    "message":  "Unexpected value in enum"
+    "message":  "Got an error during or right after parsing `enum foo`: Unexpected value in enum"
 ,   "line":     1
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/exception.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/exception.json
@@ -1,4 +1,4 @@
 {
-    "message": "Unrecognised tokens",
+    "message": "Got an error before parsing any named definition: Unrecognised tokens",
     "line": 4
 }
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/iterator.json
@@ -0,0 +1,4 @@
+{
+    "message": "Got an error during or right after parsing `interface SessionManager`: Invalid operation",
+    "line": 5
+}
--- 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
@@ -1,4 +1,4 @@
 {
-    "message": "Missing second type argument in maplike declaration",
+    "message": "Got an error during or right after parsing `interface MapLikeOneType`: Missing second type argument in maplike declaration",
     "line": 2
-}
\ No newline at end of file
+}
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/module.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/module.json
@@ -1,4 +1,4 @@
 {
-    "message":  "Unrecognised tokens"
+    "message":  "Got an error before parsing any named definition: Unrecognised tokens"
 ,   "line":     2
 }
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/no-semicolon-callback.json
@@ -0,0 +1,4 @@
+{
+    "message": "Got an error during or right after parsing `callback interface NoSemicolon`: Missing semicolon after interface",
+    "line": 5
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/no-semicolon.json
@@ -0,0 +1,4 @@
+{
+    "message": "Got an error during or right after parsing `partial interface NoSemicolon`: Missing semicolon after interface",
+    "line": 5
+}
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableany.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableany.json
@@ -1,4 +1,4 @@
 {
-    "message":  "Type any cannot be made nullable"
+    "message":  "Got an error during or right after parsing `interface NonNullable`: Type any cannot be made nullable"
 ,   "line":     2
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableobjects.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/nonnullableobjects.json
@@ -1,4 +1,4 @@
 {
-    "message":  "Can't nullable more than once"
+    "message":  "Got an error during or right after parsing `interface NonNullable`: Can't nullable more than once"
 ,   "line":     4
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/promise-with-extended-attribute.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/promise-with-extended-attribute.json
@@ -1,4 +1,4 @@
 {
-    "message": "Promise type cannot have extended attribute",
+    "message": "Got an error during or right after parsing `interface Foo`: Promise type cannot have extended attribute",
     "line": 2
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/raises.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/raises.json
@@ -1,4 +1,4 @@
 {
-    "message":  "Unterminated attribute"
+    "message":  "Got an error during or right after parsing `interface Person`: Unterminated attribute"
 ,   "line":     5
 }
--- 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
@@ -1,4 +1,4 @@
 {
-    "message": "Invalid operation",
+    "message": "Got an error during or right after parsing `interface ReadonlyIterable`: Invalid operation",
     "line": 2
-}
\ No newline at end of file
+}
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key-with-extended-attribute.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key-with-extended-attribute.json
@@ -1,4 +1,4 @@
 {
-    "message": "Record key cannot have extended attribute",
+    "message": "Got an error during or right after parsing `interface Foo`: Record key cannot have extended attribute",
     "line": 2
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/record-key.json
@@ -1,4 +1,4 @@
 {
-    "message": "Record key must be DOMString, USVString, or ByteString",
+    "message": "Got an error during or right after parsing `interface Foo`: Record key must be DOMString, USVString, or ByteString",
     "line": 2
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/scopedname.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/scopedname.json
@@ -1,4 +1,4 @@
 {
-    "message":  "No name in typedef"
+    "message":  "Got an error before parsing any named definition: No name in typedef"
 ,   "line":     2
 }
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json
@@ -1,4 +1,4 @@
 {
-    "message":  "Attributes cannot accept sequence types"
+    "message":  "Got an error during or right after parsing `interface sequenceAsAttribute`: Attributes cannot accept sequence types"
 ,   "line":     2
 }
--- 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
@@ -1,4 +1,4 @@
 {
-    "message": "Unterminated setlike declaration",
+    "message": "Got an error during or right after parsing `interface SetLikeTwoTypes`: Unterminated setlike declaration",
     "line": 2
-}
\ No newline at end of file
+}
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/setter-creator.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/setter-creator.json
@@ -1,4 +1,4 @@
 {
-    "message": "Invalid operation",
+    "message": "Got an error during or right after parsing `interface OrderedMap`: Invalid operation",
     "line": 3
 }
--- 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
@@ -1,4 +1,4 @@
 {
-    "message":  "Invalid operation"
+    "message":  "Got an error during or right after parsing `interface Dictionary`: Invalid operation"
 ,   "line":     6
 }
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/stray-slash.json
@@ -0,0 +1,4 @@
+{
+    "message":  "Got an error before parsing any named definition: Unrecognised tokens"
+,   "line":     2
+}
--- a/testing/web-platform/tests/resources/webidl2/test/invalid/json/stringconstants.json
+++ b/testing/web-platform/tests/resources/webidl2/test/invalid/json/stringconstants.json
@@ -1,4 +1,4 @@
 {
-    "message":  "No value for const"
+    "message":  "Got an error during or right after parsing `interface Util`: No value for const"
 ,   "line":     2
 }
--- 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
@@ -1,4 +1,4 @@
 {
-    "message":  "Invalid operation"
+    "message":  "Got an error during or right after parsing `interface Widget`: Invalid operation"
 ,   "line":     14
-}
\ No newline at end of file
+}
--- a/testing/web-platform/tests/resources/webidl2/test/syntax.js
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax.js
@@ -1,39 +1,19 @@
 "use strict";
 
-const wp = require("../lib/webidl2");
+const { collect } = require("./util/collect");
 const expect = require("expect");
-const pth = require("path");
-const fs = require("fs");
-const jdp = require("jsondiffpatch");
 const debug = true;
 
 describe("Parses all of the IDLs to produce the correct ASTs", () => {
-  const dir = pth.join(__dirname, "syntax/idl");
-  const skip = {}; // use if we have a broken test
-  const idls = fs.readdirSync(dir)
-    .filter(it => (/\.widl$/).test(it) && !skip[it])
-    .map(it => pth.join(dir, it));
-  const jsons = idls.map(it => pth.join(__dirname, "syntax/json", pth.basename(it).replace(".widl", ".json")));
-
-  for (let i = 0, n = idls.length; i < n; i++) {
-    const idl = idls[i];
-    const json = jsons[i];
-
-    it(`should produce the same AST for ${idl}`, () => {
+  for (const test of collect("syntax")) {
+    it(`should produce the same AST for ${test.path}`, () => {
       try {
-        const optFile = pth.join(__dirname, "syntax/opt", pth.basename(json));
-        let opt = undefined;
-        if (fs.existsSync(optFile))
-          opt = JSON.parse(fs.readFileSync(optFile, "utf8"));
-        const diff = jdp.diff(JSON.parse(fs.readFileSync(json, "utf8")),
-          wp.parse(fs.readFileSync(idl, "utf8").replace(/\r\n/g, "\n"), opt));
-        if (diff && debug) console.log(JSON.stringify(diff, null, 4));
-        expect(diff).toBe(undefined);
+        expect(test.diff()).toBeFalsy();
       }
       catch (e) {
         console.log(e.toString());
         throw e;
       }
     });
   }
 });
--- 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
@@ -15,9 +15,15 @@ interface IdInterface {};
   Constructor,
   Constructor(double radius)
 ]
 interface Circle {
   attribute double r;
   attribute double cx;
   attribute double cy;
   readonly attribute double circumference;
-};
\ No newline at end of file
+};
+
+// Extracted from https://heycam.github.io/webidl/#idl-annotated-types on 2017-12-15
+[Exposed=Window]
+interface I {
+    attribute [XAttr] (long or Node) attrib;
+};
rename from testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-union.idl
rename to testing/web-platform/tests/resources/webidl2/test/syntax/idl/typedef-union.widl
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/allowany.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/allowany.json
@@ -7,16 +7,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "g",
                 "arguments": [],
@@ -25,29 +26,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "g",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "B"
                         },
                         "name": "b"
                     }
@@ -57,16 +60,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "g",
                 "arguments": [
@@ -77,16 +81,17 @@
                             {
                                 "name": "AllowAny",
                                 "arguments": null,
                                 "type": "extended-attribute",
                                 "rhs": null
                             }
                         ],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "s"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/attributes.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/attributes.json
@@ -6,22 +6,23 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned short"
                 },
                 "name": "age",
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/callback.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/callback.json
@@ -1,25 +1,27 @@
 [
     {
         "type": "callback",
         "name": "AsyncOperationCallback",
         "idlType": {
+            "type": "return-type",
             "sequence": false,
             "generic": null,
             "nullable": false,
             "union": false,
             "idlType": "void"
         },
         "arguments": [
             {
                 "optional": false,
                 "variadic": false,
                 "extAttrs": [],
                 "idlType": {
+                    "type": "argument-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "status"
             }
@@ -34,29 +36,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "eventOccurred",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "details"
                     }
@@ -66,41 +70,44 @@
         ],
         "inheritance": null,
         "extAttrs": []
     },
     {
         "type": "callback",
         "name": "SortCallback",
         "idlType": {
+            "type": "return-type",
             "sequence": false,
             "generic": null,
             "nullable": false,
             "union": false,
             "idlType": "boolean"
         },
         "arguments": [
             {
                 "optional": false,
                 "variadic": false,
                 "extAttrs": [],
                 "idlType": {
+                    "type": "argument-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "any"
                 },
                 "name": "a"
             },
             {
                 "optional": false,
                 "variadic": false,
                 "extAttrs": [],
                 "idlType": {
+                    "type": "argument-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "any"
                 },
                 "name": "b"
             }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/constants.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/constants.json
@@ -2,97 +2,121 @@
     {
         "type": "interface",
         "name": "Util",
         "partial": false,
         "members": [
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "boolean",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "boolean"
+                },
                 "name": "DEBUG",
                 "value": {
                     "type": "boolean",
                     "value": false
                 },
                 "extAttrs": []
             },
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "short",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "short"
+                },
                 "name": "negative",
                 "value": {
                     "type": "number",
                     "value": "-1"
                 },
                 "extAttrs": []
             },
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "octet",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "octet"
+                },
                 "name": "LF",
                 "value": {
                     "type": "number",
                     "value": "10"
                 },
                 "extAttrs": []
             },
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "unsigned long",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "unsigned long"
+                },
                 "name": "BIT_MASK",
                 "value": {
                     "type": "number",
                     "value": "0x0000fc00"
                 },
                 "extAttrs": []
             },
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "float",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "float"
+                },
                 "name": "AVOGADRO",
                 "value": {
                     "type": "number",
                     "value": "6.022e23"
                 },
                 "extAttrs": []
             },
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "unrestricted float",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "unrestricted float"
+                },
                 "name": "sobig",
                 "value": {
                     "type": "Infinity",
                     "negative": false
                 },
                 "extAttrs": []
             },
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "unrestricted double",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "unrestricted double"
+                },
                 "name": "minusonedividedbyzero",
                 "value": {
                     "type": "Infinity",
                     "negative": true
                 },
                 "extAttrs": []
             },
             {
                 "type": "const",
                 "nullable": false,
-                "idlType": "short",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "short"
+                },
                 "name": "notanumber",
                 "value": {
                     "type": "NaN"
                 },
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/constructor.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/constructor.json
@@ -6,64 +6,68 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "r",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "cx",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "cy",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "circumference",
                 "extAttrs": []
@@ -80,16 +84,17 @@
             {
                 "name": "Constructor",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "radius"
                     }
--- 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
@@ -4,16 +4,17 @@
         "name": "PaintOptions",
         "partial": false,
         "members": [
             {
                 "type": "field",
                 "name": "fillPattern",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": true,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "extAttrs": [],
                 "default": {
@@ -21,32 +22,34 @@
                     "value": "black"
                 }
             },
             {
                 "type": "field",
                 "name": "strokePattern",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": true,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "extAttrs": [],
                 "default": {
                     "type": "null"
                 }
             },
             {
                 "type": "field",
                 "name": "position",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Point"
                 },
                 "extAttrs": []
             }
@@ -59,21 +62,22 @@
         "name": "WetPaintOptions",
         "partial": false,
         "members": [
             {
                 "type": "field",
                 "name": "hydrometry",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "extAttrs": []
             }
         ],
         "inheritance": "PaintOptions",
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/dictionary.json
@@ -4,16 +4,17 @@
         "name": "PaintOptions",
         "partial": false,
         "members": [
             {
                 "type": "field",
                 "name": "fillPattern",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": true,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "extAttrs": [],
                 "default": {
@@ -21,50 +22,54 @@
                     "value": "black"
                 }
             },
             {
                 "type": "field",
                 "name": "strokePattern",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": true,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "extAttrs": [],
                 "default": {
                     "type": "null"
                 }
             },
             {
                 "type": "field",
                 "name": "position",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Point"
                 },
                 "extAttrs": []
             },
             {
                 "type": "field",
                 "name": "seq",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": true,
                     "generic": "sequence",
                     "nullable": false,
                     "union": false,
                     "idlType": {
+                        "type": "dictionary-type",
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "long"
                     }
                 },
                 "extAttrs": [],
@@ -73,16 +78,17 @@
                     "value": []
                 }
             },
             {
                 "type": "field",
                 "name": "reqSeq",
                 "required": true,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "long"
                 },
                 "extAttrs": []
             }
@@ -95,33 +101,35 @@
         "name": "A",
         "partial": true,
         "members": [
             {
                 "type": "field",
                 "name": "h",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "long"
                 },
                 "extAttrs": []
             },
             {
                 "type": "field",
                 "name": "d",
                 "required": false,
                 "idlType": {
+                    "type": "dictionary-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "long"
                 },
                 "extAttrs": []
             }
         ],
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- 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
@@ -2,9 +2,9 @@
     {
         "type": "interface",
         "name": "Documentation",
         "partial": false,
         "members": [],
         "inheritance": null,
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/documentation.json
@@ -2,9 +2,9 @@
     {
         "type": "interface",
         "name": "Documentation",
         "partial": false,
         "members": [],
         "inheritance": null,
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/enum.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/enum.json
@@ -1,47 +1,58 @@
 [
     {
         "type": "enum",
         "name": "MealType",
         "values": [
-            { "type": "string", "value": "rice" },
-            { "type": "string", "value": "noodles" },
-            { "type": "string", "value": "other" }
+            {
+                "type": "string",
+                "value": "rice"
+            },
+            {
+                "type": "string",
+                "value": "noodles"
+            },
+            {
+                "type": "string",
+                "value": "other"
+            }
         ],
         "extAttrs": []
     },
     {
         "type": "interface",
         "name": "Meal",
         "partial": false,
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "MealType"
                 },
                 "name": "type",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "size",
                 "extAttrs": []
@@ -49,42 +60,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "initialize",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "MealType"
                         },
                         "name": "type"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "size"
                     }
@@ -94,15 +108,24 @@
         ],
         "inheritance": null,
         "extAttrs": []
     },
     {
         "type": "enum",
         "name": "AltMealType",
         "values": [
-            { "type": "string", "value": "rice" },
-            { "type": "string", "value": "noodles" },
-            { "type": "string", "value": "other" }
+            {
+                "type": "string",
+                "value": "rice"
+            },
+            {
+                "type": "string",
+                "value": "noodles"
+            },
+            {
+                "type": "string",
+                "value": "other"
+            }
         ],
         "extAttrs": []
     }
 ]
--- 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
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "propertyCount",
                 "extAttrs": []
@@ -23,29 +24,31 @@
             {
                 "type": "operation",
                 "getter": true,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "getProperty",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     }
@@ -55,42 +58,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": true,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "setProperty",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "propertyValue"
                     }
@@ -108,16 +114,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "propertyCount",
                 "extAttrs": []
@@ -125,29 +132,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "getProperty",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     }
@@ -157,42 +166,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "setProperty",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "propertyValue"
                     }
@@ -202,29 +214,31 @@
             {
                 "type": "operation",
                 "getter": true,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": null,
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     }
@@ -234,42 +248,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": true,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": null,
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "propertyValue"
                     }
--- 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
@@ -25,144 +25,210 @@
                 "rhs": {
                     "type": "identifier",
                     "value": "ServiceWorker"
                 }
             }
         ]
     },
     {
-      "type": "interface",
-      "name": "IdInterface",
-      "partial": false,
-      "members": [],
-      "inheritance": null,
-      "extAttrs": [
-        {
-          "name": "IntAttr",
-          "arguments": null,
-          "type": "extended-attribute",
-          "rhs": {
-            "type": "integer",
-            "value": "0"
-          }
-        },
-        {
-          "name": "FloatAttr",
-          "arguments": null,
-          "type": "extended-attribute",
-          "rhs": {
-            "type": "float",
-            "value": "3.14"
-          }
-        },
-        {
-          "name": "StringAttr",
-          "arguments": null,
-          "type": "extended-attribute",
-          "rhs": {
-            "type": "string",
-            "value": "\"abc\""
-          }
-        }
-      ]
+        "type": "interface",
+        "name": "IdInterface",
+        "partial": false,
+        "members": [],
+        "inheritance": null,
+        "extAttrs": [
+            {
+                "name": "IntAttr",
+                "arguments": null,
+                "type": "extended-attribute",
+                "rhs": {
+                    "type": "integer",
+                    "value": "0"
+                }
+            },
+            {
+                "name": "FloatAttr",
+                "arguments": null,
+                "type": "extended-attribute",
+                "rhs": {
+                    "type": "float",
+                    "value": "3.14"
+                }
+            },
+            {
+                "name": "StringAttr",
+                "arguments": null,
+                "type": "extended-attribute",
+                "rhs": {
+                    "type": "string",
+                    "value": "\"abc\""
+                }
+            }
+        ]
     },
     {
-      "type": "interface",
-      "name": "Circle",
-      "partial": false,
-      "members": [
-        {
-          "type": "attribute",
-          "static": false,
-          "stringifier": false,
-          "inherit": false,
-          "readonly": false,
-          "idlType": {
-            "sequence": false,
-            "generic": null,
-            "nullable": false,
-            "union": false,
-            "idlType": "double"
-          },
-          "name": "r",
-          "extAttrs": []
-        },
-        {
-          "type": "attribute",
-          "static": false,
-          "stringifier": false,
-          "inherit": false,
-          "readonly": false,
-          "idlType": {
-            "sequence": false,
-            "generic": null,
-            "nullable": false,
-            "union": false,
-            "idlType": "double"
-          },
-          "name": "cx",
-          "extAttrs": []
-        },
-        {
-          "type": "attribute",
-          "static": false,
-          "stringifier": false,
-          "inherit": false,
-          "readonly": false,
-          "idlType": {
-            "sequence": false,
-            "generic": null,
-            "nullable": false,
-            "union": false,
-            "idlType": "double"
-          },
-          "name": "cy",
-          "extAttrs": []
-        },
-        {
-          "type": "attribute",
-          "static": false,
-          "stringifier": false,
-          "inherit": false,
-          "readonly": true,
-          "idlType": {
-            "sequence": false,
-            "generic": null,
-            "nullable": false,
-            "union": false,
-            "idlType": "double"
-          },
-          "name": "circumference",
-          "extAttrs": []
-        }
-      ],
-      "inheritance": null,
-      "extAttrs": [
-        {
-          "name": "Constructor",
-          "arguments": null,
-          "type": "extended-attribute",
-          "rhs": null
-        },
-        {
-          "name": "Constructor",
-          "arguments": [
+        "type": "interface",
+        "name": "Circle",
+        "partial": false,
+        "members": [
+            {
+                "type": "attribute",
+                "static": false,
+                "stringifier": false,
+                "inherit": false,
+                "readonly": false,
+                "idlType": {
+                    "type": "attribute-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "double"
+                },
+                "name": "r",
+                "extAttrs": []
+            },
+            {
+                "type": "attribute",
+                "static": false,
+                "stringifier": false,
+                "inherit": false,
+                "readonly": false,
+                "idlType": {
+                    "type": "attribute-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "double"
+                },
+                "name": "cx",
+                "extAttrs": []
+            },
+            {
+                "type": "attribute",
+                "static": false,
+                "stringifier": false,
+                "inherit": false,
+                "readonly": false,
+                "idlType": {
+                    "type": "attribute-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "double"
+                },
+                "name": "cy",
+                "extAttrs": []
+            },
+            {
+                "type": "attribute",
+                "static": false,
+                "stringifier": false,
+                "inherit": false,
+                "readonly": true,
+                "idlType": {
+                    "type": "attribute-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "double"
+                },
+                "name": "circumference",
+                "extAttrs": []
+            }
+        ],
+        "inheritance": null,
+        "extAttrs": [
+            {
+                "name": "Constructor",
+                "arguments": null,
+                "type": "extended-attribute",
+                "rhs": null
+            },
             {
-              "optional": false,
-              "variadic": false,
-              "extAttrs": [],
-              "idlType": {
-                "sequence": false,
-                "generic": null,
-                "nullable": false,
-                "union": false,
-                "idlType": "double"
-              },
-              "name": "radius"
+                "name": "Constructor",
+                "arguments": [
+                    {
+                        "optional": false,
+                        "variadic": false,
+                        "extAttrs": [],
+                        "idlType": {
+                            "type": "argument-type",
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": false,
+                            "union": false,
+                            "idlType": "double"
+                        },
+                        "name": "radius"
+                    }
+                ],
+                "type": "extended-attribute",
+                "rhs": null
             }
-          ],
-          "type": "extended-attribute",
-          "rhs": null
-        }
-      ]
+        ]
+    },
+    {
+        "type": "interface",
+        "name": "I",
+        "partial": false,
+        "members": [
+            {
+                "type": "attribute",
+                "static": false,
+                "stringifier": false,
+                "inherit": false,
+                "readonly": false,
+                "idlType": {
+                    "type": "attribute-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": true,
+                    "idlType": [
+                        {
+                            "type": null,
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": false,
+                            "union": false,
+                            "idlType": "long"
+                        },
+                        {
+                            "type": null,
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": false,
+                            "union": false,
+                            "idlType": "Node"
+                        }
+                    ],
+                    "extAttrs": [
+                        {
+                            "name": "XAttr",
+                            "arguments": null,
+                            "type": "extended-attribute",
+                            "rhs": null
+                        }
+                    ]
+                },
+                "name": "attrib",
+                "extAttrs": []
+            }
+        ],
+        "inheritance": null,
+        "extAttrs": [
+            {
+                "name": "Exposed",
+                "arguments": null,
+                "type": "extended-attribute",
+                "rhs": {
+                    "type": "identifier",
+                    "value": "Window"
+                }
+            }
+        ]
     }
 ]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/generic.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/generic.json
@@ -7,31 +7,35 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": "Promise",
                     "nullable": false,
                     "union": false,
                     "idlType": {
+                        "type": "return-type",
                         "sequence": false,
                         "generic": "ResponsePromise",
                         "nullable": false,
                         "union": false,
                         "idlType": {
+                            "type": "return-type",
                             "sequence": true,
                             "generic": "sequence",
                             "nullable": false,
                             "union": false,
                             "idlType": {
+                                "type": "return-type",
                                 "sequence": false,
                                 "generic": null,
                                 "nullable": true,
                                 "union": false,
                                 "idlType": "DOMString"
                             }
                         }
                     }
@@ -42,21 +46,23 @@
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": "Promise",
                     "nullable": false,
                     "union": false,
                     "idlType": {
+                        "type": "attribute-type",
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "DOMString"
                     }
                 },
                 "name": "baz",
@@ -74,21 +80,23 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": "Promise",
                     "nullable": false,
                     "union": false,
                     "idlType": {
+                        "type": "return-type",
                         "sequence": false,
                         "generic": null,
                         "nullable": true,
                         "union": false,
                         "idlType": "Client"
                     }
                 },
                 "name": "getServiced",
@@ -98,21 +106,23 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": "Promise",
                     "nullable": false,
                     "union": false,
                     "idlType": {
+                        "type": "return-type",
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "any"
                     }
                 },
                 "name": "reloadAll",
@@ -131,21 +141,23 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": "ResponsePromise",
                     "nullable": false,
                     "union": false,
                     "idlType": {
+                        "type": "return-type",
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "any"
                     }
                 },
                 "name": "default",
--- 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
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "propertyCount",
                 "extAttrs": []
@@ -23,29 +24,31 @@
             {
                 "type": "operation",
                 "getter": true,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": null,
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     }
@@ -55,42 +58,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": true,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": null,
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "propertyName"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "propertyValue"
                     }
--- 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
@@ -1,12 +1,13 @@
 [
     {
         "type": "typedef",
         "idlType": {
+            "type": "typedef-type",
             "sequence": false,
             "generic": null,
             "nullable": false,
             "union": false,
             "idlType": "float"
         },
         "name": "number",
         "extAttrs": []
@@ -19,29 +20,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "object"
                 },
                 "name": "createObject",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "interface"
                     }
@@ -51,29 +54,31 @@
             {
                 "type": "operation",
                 "getter": true,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": null,
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "keyName"
                     }
@@ -91,32 +96,34 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "boolean"
                 },
                 "name": "const",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": true,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "value",
                 "extAttrs": []
@@ -133,29 +140,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "op",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "object"
                         },
                         "name": "interface"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/implements.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/implements.json
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned short"
                 },
                 "name": "nodeType",
                 "extAttrs": []
@@ -32,55 +33,59 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "addEventListener",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "type"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "EventListener"
                         },
                         "name": "listener"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "boolean"
                         },
                         "name": "useCapture"
                     }
--- 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
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "size",
                 "extAttrs": []
@@ -23,29 +24,31 @@
             {
                 "type": "operation",
                 "getter": true,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "any"
                 },
                 "name": "getByIndex",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "unsigned long"
                         },
                         "name": "index"
                     }
@@ -55,42 +58,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": true,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "setByIndex",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "unsigned long"
                         },
                         "name": "index"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "any"
                         },
                         "name": "value"
                     }
@@ -100,29 +106,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": true,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "removeByIndex",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "unsigned long"
                         },
                         "name": "index"
                     }
@@ -132,29 +140,31 @@
             {
                 "type": "operation",
                 "getter": true,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "any"
                 },
                 "name": "get",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "name"
                     }
@@ -164,42 +174,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": true,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "set",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "name"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "any"
                         },
                         "name": "value"
                     }
@@ -209,29 +222,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": true,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "remove",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "name"
                     }
--- 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
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "name",
                 "extAttrs": []
@@ -31,38 +32,40 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned short"
                 },
                 "name": "age",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": true,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "name",
                 "extAttrs": []
             }
         ],
         "inheritance": "Animal",
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- 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
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "name",
                 "extAttrs": []
@@ -31,16 +32,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Dog"
                 },
                 "name": "pet",
                 "extAttrs": []
@@ -56,22 +58,23 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Human"
                 },
                 "name": "owner",
                 "extAttrs": []
             }
         ],
         "inheritance": "Animal",
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterable.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/iterable.json
@@ -1,45 +1,50 @@
 [
     {
         "type": "interface",
         "name": "IterableOne",
         "partial": false,
         "members": [
             {
                 "type": "iterable",
-                "idlType": {
-                    "sequence": false,
-                    "generic": null,
-                    "nullable": false,
-                    "union": false,
-                    "idlType": "long"
-                },
+                "idlType": [
+                    {
+                        "type": null,
+                        "sequence": false,
+                        "generic": null,
+                        "nullable": false,
+                        "union": false,
+                        "idlType": "long"
+                    }
+                ],
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     },
     {
         "type": "interface",
         "name": "IterableTwo",
         "partial": false,
         "members": [
             {
                 "type": "iterable",
                 "idlType": [
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "short"
                     },
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": true,
                         "union": false,
                         "idlType": "double"
                     }
                 ],
                 "extAttrs": []
@@ -50,31 +55,33 @@
     },
     {
         "type": "interface",
         "name": "IterableThree",
         "partial": false,
         "members": [
             {
                 "type": "iterable",
-                "idlType": {
-                    "sequence": false,
-                    "generic": null,
-                    "nullable": false,
-                    "union": false,
-                    "idlType": "long",
-                    "extAttrs": [
-                        {
-                            "name": "XAttr",
-                            "arguments": null,
-                            "type": "extended-attribute",
-                            "rhs": null
-                        }
-                    ]
-                },
+                "idlType": [
+                    {
+                        "type": null,
+                        "sequence": false,
+                        "generic": null,
+                        "nullable": false,
+                        "union": false,
+                        "idlType": "long",
+                        "extAttrs": [
+                            {
+                                "name": "XAttr",
+                                "arguments": null,
+                                "type": "extended-attribute",
+                                "rhs": null
+                            }
+                        ]
+                    }
+                ],
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
 ]
-
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/legacyiterable.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/legacyiterable.json
@@ -1,23 +1,25 @@
 [
     {
         "type": "interface",
         "name": "LegacyIterable",
         "partial": false,
         "members": [
             {
                 "type": "legacyiterable",
-                "idlType": {
-                    "sequence": false,
-                    "generic": null,
-                    "nullable": false,
-                    "union": false,
-                    "idlType": "long"
-                },
+                "idlType": [
+                    {
+                        "type": null,
+                        "sequence": false,
+                        "generic": null,
+                        "nullable": false,
+                        "union": false,
+                        "idlType": "long"
+                    }
+                ],
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
 ]
-
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/maplike.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/maplike.json
@@ -3,23 +3,25 @@
         "type": "interface",
         "name": "MapLike",
         "partial": false,
         "members": [
             {
                 "type": "maplike",
                 "idlType": [
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "long"
                     },
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "float"
                     }
                 ],
                 "readonly": false,
@@ -33,23 +35,25 @@
         "type": "interface",
         "name": "ReadOnlyMapLike",
         "partial": false,
         "members": [
             {
                 "type": "maplike",
                 "idlType": [
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "long"
                     },
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "float"
                     }
                 ],
                 "readonly": true,
@@ -63,31 +67,33 @@
         "type": "interface",
         "name": "I",
         "partial": false,
         "members": [
             {
                 "type": "maplike",
                 "idlType": [
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "DOMString",
                         "extAttrs": [
                             {
                                 "name": "XAttr2",
                                 "arguments": null,
                                 "type": "extended-attribute",
                                 "rhs": null
                             }
                         ]
                     },
                     {
+                        "type": null,
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "long",
                         "extAttrs": [
                             {
                                 "name": "XAttr3",
@@ -101,9 +107,8 @@
                 "readonly": false,
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
 ]
-
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/mixin.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/mixin.json
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Crypto"
                 },
                 "name": "crypto",
                 "extAttrs": []
@@ -42,16 +43,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Crypto"
                 },
                 "name": "crypto",
                 "extAttrs": []
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/namedconstructor.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/namedconstructor.json
@@ -18,16 +18,17 @@
             {
                 "name": "NamedConstructor",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "src"
                     }
@@ -35,9 +36,9 @@
                 "type": "extended-attribute",
                 "rhs": {
                     "type": "identifier",
                     "value": "Audio"
                 }
             }
         ]
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/namespace.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/namespace.json
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Vector"
                 },
                 "name": "unit",
                 "extAttrs": []
@@ -23,42 +24,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "double"
                 },
                 "name": "dotProduct",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Vector"
                         },
                         "name": "x"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Vector"
                         },
                         "name": "y"
                     }
@@ -68,42 +72,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Vector"
                 },
                 "name": "crossProduct",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Vector"
                         },
                         "name": "x"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Vector"
                         },
                         "name": "y"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
@@ -7,29 +7,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "any"
                 },
                 "name": "lookupEntry",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "unsigned long"
                         },
                         "name": "key"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullable.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullable.json
@@ -2,17 +2,20 @@
     {
         "type": "interface",
         "name": "MyConstants",
         "partial": false,
         "members": [
             {
                 "type": "const",
                 "nullable": true,
-                "idlType": "boolean",
+                "idlType": {
+                    "type": "const-type",
+                    "idlType": "boolean"
+                },
                 "name": "ARE_WE_THERE_YET",
                 "value": {
                     "type": "boolean",
                     "value": false
                 },
                 "extAttrs": []
             }
         ],
@@ -26,22 +29,23 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": true,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "namespaceURI",
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullableobjects.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/nullableobjects.json
@@ -23,29 +23,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": true,
                             "union": false,
                             "idlType": "A"
                         },
                         "name": "x"
                     }
@@ -55,29 +57,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": true,
                             "union": false,
                             "idlType": "B"
                         },
                         "name": "x"
                     }
--- 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
@@ -7,68 +7,73 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "object"
                 },
                 "name": "createColor",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "v1"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "v2"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "v3"
                     },
                     {
                         "optional": true,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "alpha",
                         "default": {
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/overloading.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/overloading.json
@@ -23,29 +23,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "A"
                         },
                         "name": "x"
                     }
@@ -55,29 +57,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "B"
                         },
                         "name": "x"
                     }
@@ -96,29 +100,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "a"
                     }
@@ -128,16 +134,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [
@@ -148,42 +155,45 @@
                             {
                                 "name": "AllowAny",
                                 "arguments": null,
                                 "type": "extended-attribute",
                                 "rhs": null
                             }
                         ],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "a"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "b"
                     },
                     {
                         "optional": false,
                         "variadic": true,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "c"
                     }
@@ -193,16 +203,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [],
@@ -211,68 +222,73 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "long"
                         },
                         "name": "a"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "b"
                     },
                     {
                         "optional": true,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "c"
                     },
                     {
                         "optional": false,
                         "variadic": true,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float"
                         },
                         "name": "d"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/overridebuiltins.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/overridebuiltins.json
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "length",
                 "extAttrs": []
@@ -23,29 +24,31 @@
             {
                 "type": "operation",
                 "getter": true,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "lookup",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "key"
                     }
--- 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
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "bar",
                 "extAttrs": []
@@ -31,21 +32,22 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "quux",
                 "extAttrs": []
             }
         ],
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/primitives.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/primitives.json
@@ -6,278 +6,295 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "boolean"
                 },
                 "name": "truth",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "byte"
                 },
                 "name": "character",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "octet"
                 },
                 "name": "value",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "short"
                 },
                 "name": "number",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned short"
                 },
                 "name": "positive",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "long"
                 },
                 "name": "big",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "bigpositive",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "long long"
                 },
                 "name": "bigbig",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long long"
                 },
                 "name": "bigbigpositive",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "real",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "double"
                 },
                 "name": "bigreal",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unrestricted float"
                 },
                 "name": "realwithinfinity",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unrestricted double"
                 },
                 "name": "bigrealwithinfinity",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "string",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "ByteString"
                 },
                 "name": "bytes",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Date"
                 },
                 "name": "date",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "RegExp"
                 },
                 "name": "regexp",
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/prototyperoot.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/prototyperoot.json
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned short"
                 },
                 "name": "nodeType",
                 "extAttrs": []
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/putforwards.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/putforwards.json
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Name"
                 },
                 "name": "name",
                 "extAttrs": [
@@ -32,22 +33,23 @@
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned short"
                 },
                 "name": "age",
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
-]
\ No newline at end of file
+]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/record.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/record.json
@@ -7,47 +7,52 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "foo",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": true,
                             "generic": "sequence",
                             "nullable": false,
                             "union": false,
                             "idlType": {
+                                "type": "argument-type",
                                 "sequence": false,
                                 "generic": "record",
                                 "nullable": false,
                                 "union": false,
                                 "idlType": [
                                     {
+                                        "type": "argument-type",
                                         "sequence": false,
                                         "generic": null,
                                         "nullable": false,
                                         "union": false,
                                         "idlType": "ByteString"
                                     },
                                     {
+                                        "type": "argument-type",
                                         "sequence": false,
                                         "generic": null,
                                         "nullable": false,
                                         "union": false,
                                         "idlType": "any"
                                     }
                                 ]
                             }
@@ -60,42 +65,47 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": "record",
                     "nullable": false,
                     "union": false,
                     "idlType": [
                         {
+                            "type": "return-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         {
+                            "type": "return-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": true,
                             "union": true,
                             "idlType": [
                                 {
+                                    "type": null,
                                     "sequence": false,
                                     "generic": null,
                                     "nullable": false,
                                     "union": false,
                                     "idlType": "float"
                                 },
                                 {
+                                    "type": null,
                                     "sequence": false,
                                     "generic": null,
                                     "nullable": false,
                                     "union": false,
                                     "idlType": "DOMString"
                                 }
                             ]
                         }
@@ -108,16 +118,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "record"
                 },
                 "name": "baz",
                 "arguments": [],
@@ -129,29 +140,32 @@
             {
                 "name": "Constructor",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": "record",
                             "nullable": false,
                             "union": false,
                             "idlType": [
                                 {
+                                    "type": "argument-type",
                                     "sequence": false,
                                     "generic": null,
                                     "nullable": false,
                                     "union": false,
                                     "idlType": "USVString"
                                 },
                                 {
+                                    "type": "argument-type",
                                     "sequence": false,
                                     "generic": null,
                                     "nullable": false,
                                     "union": false,
                                     "idlType": "USVString"
                                 }
                             ]
                         },
@@ -171,29 +185,32 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": "record",
                     "nullable": false,
                     "union": false,
                     "idlType": [
                         {
+                            "type": "return-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         {
+                            "type": "return-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "float",
                             "extAttrs": [
                                 {
                                     "name": "XAttr",
--- 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
@@ -6,32 +6,34 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "width",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "height",
                 "extAttrs": []
@@ -48,16 +50,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "boolean"
                 },
                 "name": "isMouseOver",
                 "arguments": [],
@@ -66,29 +69,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "setDimensions",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Dimensions"
                         },
                         "name": "size"
                     }
@@ -98,42 +103,45 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "setDimensions",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "unsigned long"
                         },
                         "name": "width"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "unsigned long"
                         },
                         "name": "height"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/replaceable.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/replaceable.json
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "value",
                 "extAttrs": [
@@ -30,16 +31,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "increment",
                 "arguments": [],
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/sequence.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/sequence.json
@@ -7,34 +7,37 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "drawPolygon",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": true,
                             "generic": "sequence",
                             "nullable": false,
                             "union": false,
                             "idlType": {
+                                "type": "argument-type",
                                 "sequence": false,
                                 "generic": null,
                                 "nullable": false,
                                 "union": false,
                                 "idlType": "float"
                             }
                         },
                         "name": "coordinates"
@@ -45,21 +48,23 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": true,
                     "generic": "sequence",
                     "nullable": false,
                     "union": false,
                     "idlType": {
+                        "type": "return-type",
                         "sequence": false,
                         "generic": null,
                         "nullable": false,
                         "union": false,
                         "idlType": "float"
                     }
                 },
                 "name": "getInflectionPoints",
@@ -70,71 +75,73 @@
         "inheritance": null,
         "extAttrs": []
     },
     {
         "type": "interface",
         "name": "Foo",
         "partial": false,
         "members": [
-
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "sequence"
                 },
                 "name": "bar",
                 "arguments": [],
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     },
-
     {
         "type": "interface",
         "name": "I",
         "partial": false,
         "members": [
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "f1",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": true,
                             "generic": "sequence",
                             "nullable": false,
                             "union": false,
                             "idlType": {
+                                "type": "argument-type",
                                 "sequence": false,
                                 "generic": null,
                                 "nullable": false,
                                 "union": false,
                                 "idlType": "long",
                                 "extAttrs": [
                                     {
                                         "name": "XAttr",
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/setlike.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/setlike.json
@@ -1,74 +1,82 @@
 [
     {
         "type": "interface",
         "name": "SetLike",
         "partial": false,
         "members": [
             {
                 "type": "setlike",
-                "idlType": {
-                    "sequence": false,
-                    "generic": null,
-                    "nullable": false,
-                    "union": false,
-                    "idlType": "long"
-                },
+                "idlType": [
+                    {
+                        "type": null,
+                        "sequence": false,
+                        "generic": null,
+                        "nullable": 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,
-                    "union": false,
-                    "idlType": "long"
-                },
+                "idlType": [
+                    {
+                        "type": null,
+                        "sequence": false,
+                        "generic": null,
+                        "nullable": false,
+                        "union": false,
+                        "idlType": "long"
+                    }
+                ],
                 "readonly": true,
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     },
     {
         "type": "interface",
         "name": "SetLikeExt",
         "partial": false,
         "members": [
             {
                 "type": "setlike",
-                "idlType": {
-                    "sequence": false,
-                    "generic": null,
-                    "nullable": false,
-                    "union": false,
-                    "idlType": "long",
-                    "extAttrs": [
-                        {
-                            "name": "XAttr",
-                            "arguments": null,
-                            "type": "extended-attribute",
-                            "rhs": null
-                        }
-                    ]
-                },
+                "idlType": [
+                    {
+                        "type": null,
+                        "sequence": false,
+                        "generic": null,
+                        "nullable": false,
+                        "union": false,
+                        "idlType": "long",
+                        "extAttrs": [
+                            {
+                                "name": "XAttr",
+                                "arguments": null,
+                                "type": "extended-attribute",
+                                "rhs": null
+                            }
+                        ]
+                    }
+                ],
                 "readonly": false,
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     }
 ]
-
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/static.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/static.json
@@ -14,64 +14,68 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "cx",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "cy",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "radius",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": true,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "long"
                 },
                 "name": "triangulationCount",
                 "extAttrs": []
@@ -79,55 +83,59 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": true,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Point"
                 },
                 "name": "triangulate",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Circle"
                         },
                         "name": "c1"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Circle"
                         },
                         "name": "c2"
                     },
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Circle"
                         },
                         "name": "c3"
                     }
--- 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
@@ -6,32 +6,34 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "id",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": true,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "name",
                 "extAttrs": []
--- 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
@@ -6,48 +6,51 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "id",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": true,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "familyName",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "givenName",
                 "extAttrs": []
@@ -55,16 +58,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": true,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": null,
                 "arguments": [],
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/stringifier.json
@@ -7,16 +7,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": true,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": null,
                 "arguments": [],
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasnull.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasnull.json
@@ -6,32 +6,34 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "name",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "owner",
                 "extAttrs": []
@@ -39,16 +41,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "boolean"
                 },
                 "name": "isMemberOfBreed",
                 "arguments": [
@@ -62,16 +65,17 @@
                                 "type": "extended-attribute",
                                 "rhs": {
                                     "type": "identifier",
                                     "value": "EmptyString"
                                 }
                             }
                         ],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "breedName"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasundefined.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/treatasundefined.json
@@ -6,32 +6,34 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "name",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "DOMString"
                 },
                 "name": "owner",
                 "extAttrs": []
@@ -39,16 +41,17 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "boolean"
                 },
                 "name": "isMemberOfBreed",
                 "arguments": [
@@ -62,16 +65,17 @@
                                 "type": "extended-attribute",
                                 "rhs": {
                                     "type": "identifier",
                                     "value": "EmptyString"
                                 }
                             }
                         ],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "DOMString"
                         },
                         "name": "breedName"
                     }
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-union.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef-union.json
@@ -1,49 +1,48 @@
 [
-   {
-      "type" : "typedef",
-      "idlType" : {
-         "nullable" : false,
-         "generic" : null,
-         "union" : true,
-         "idlType" : [
-            {
-               "union" : false,
-               "generic" : null,
-               "nullable" : false,
-               "array" : false,
-               "sequence" : false,
-               "idlType" : "ImageData"
-            },
-            {
-               "generic" : null,
-               "union" : false,
-               "nullable" : false,
-               "array" : false,
-               "idlType" : "HTMLImageElement",
-               "sequence" : false
-            },
-            {
-               "array" : false,
-               "sequence" : false,
-               "idlType" : "HTMLCanvasElement",
-               "generic" : null,
-               "union" : false,
-               "nullable" : false
-            },
-            {
-               "union" : false,
-               "generic" : null,
-               "nullable" : false,
-               "array" : false,
-               "sequence" : false,
-               "idlType" : "HTMLVideoElement"
-            }
-         ],
-         "sequence" : false,
-         "array" : false
-      },
-      "name" : "TexImageSource",
-      "extAttrs" : [],
-      "typeExtAttrs" : []
-   }
+    {
+        "type": "typedef",
+        "idlType": {
+            "type": "typedef-type",
+            "sequence": false,
+            "generic": null,
+            "nullable": false,
+            "union": true,
+            "idlType": [
+                {
+                    "type": null,
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "ImageData"
+                },
+                {
+                    "type": null,
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "HTMLImageElement"
+                },
+                {
+                    "type": null,
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "HTMLCanvasElement"
+                },
+                {
+                    "type": null,
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "HTMLVideoElement"
+                }
+            ]
+        },
+        "name": "TexImageSource",
+        "extAttrs": []
+    }
 ]
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typedef.json
@@ -6,53 +6,57 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "x",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "float"
                 },
                 "name": "y",
                 "extAttrs": []
             }
         ],
         "inheritance": null,
         "extAttrs": []
     },
     {
         "type": "typedef",
         "idlType": {
+            "type": "typedef-type",
             "sequence": true,
             "generic": "sequence",
             "nullable": false,
             "union": false,
             "idlType": {
+                "type": "typedef-type",
                 "sequence": false,
                 "generic": null,
                 "nullable": false,
                 "union": false,
                 "idlType": "Point"
             }
         },
         "name": "PointSequence",
@@ -65,32 +69,34 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Point"
                 },
                 "name": "topleft",
                 "extAttrs": []
             },
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": false,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Point"
                 },
                 "name": "bottomright",
                 "extAttrs": []
@@ -106,16 +112,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "Rect"
                 },
                 "name": "bounds",
                 "extAttrs": []
@@ -123,29 +130,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "boolean"
                 },
                 "name": "pointWithinBounds",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "Point"
                         },
                         "name": "p"
                     }
@@ -155,29 +164,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "boolean"
                 },
                 "name": "allPointsWithinBounds",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "PointSequence"
                         },
                         "name": "ps"
                     }
@@ -186,16 +197,17 @@
             }
         ],
         "inheritance": null,
         "extAttrs": []
     },
     {
         "type": "typedef",
         "idlType": {
+            "type": "typedef-type",
             "sequence": false,
             "generic": null,
             "nullable": false,
             "union": false,
             "idlType": "octet",
             "extAttrs": [
                 {
                     "name": "Clamp",
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/typesuffixes.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/typesuffixes.json
@@ -7,34 +7,37 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "test",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": false,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": true,
                             "generic": "sequence",
                             "nullable": true,
                             "union": false,
                             "idlType": {
+                                "type": "argument-type",
                                 "sequence": false,
                                 "generic": null,
                                 "nullable": true,
                                 "union": false,
                                 "idlType": "DOMString"
                             }
                         },
                         "name": "foo"
--- a/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json
+++ b/testing/web-platform/tests/resources/webidl2/test/syntax/json/uniontype.json
@@ -1,118 +1,129 @@
 [
-   {
-      "partial": false,
-      "members": [
-         {
-            "idlType": {
-               "idlType": [
-                  {
-                     "union": false,
-                     "sequence": false,
-                     "generic": null,
-                     "idlType": "float",
-                     "nullable": false
-                  },
-                  {
-                     "idlType": [
+    {
+        "type": "interface",
+        "name": "Union",
+        "partial": false,
+        "members": [
+            {
+                "type": "attribute",
+                "static": false,
+                "stringifier": false,
+                "inherit": false,
+                "readonly": false,
+                "idlType": {
+                    "type": "attribute-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": true,
+                    "idlType": [
                         {
-                           "nullable": false,
-                           "idlType": "Date",
-                           "sequence": false,
-                           "generic": null,
-                           "union": false
+                            "type": null,
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": false,
+                            "union": false,
+                            "idlType": "float"
                         },
                         {
-                           "nullable": false,
-                           "idlType": "Event",
-                           "generic": null,
-                           "sequence": false,
-                           "union": false
-                        }
-                     ],
-                     "nullable": false,
-                     "sequence": false,
-                     "generic": null,
-                     "union": true
-                  },
-                  {
-                     "generic": null,
-                     "sequence": false,
-                     "idlType": [
-                        {
-                           "union": false,
-                           "sequence": false,
-                           "generic": null,
-                           "nullable": false,
-                           "idlType": "Node"
+                            "type": null,
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": false,
+                            "union": true,
+                            "idlType": [
+                                {
+                                    "type": null,
+                                    "sequence": false,
+                                    "generic": null,
+                                    "nullable": false,
+                                    "union": false,
+                                    "idlType": "Date"
+                                },
+                                {
+                                    "type": null,
+                                    "sequence": false,
+                                    "generic": null,
+                                    "nullable": false,
+                                    "union": false,
+                                    "idlType": "Event"
+                                }
+                            ]
                         },
                         {
-                           "nullable": false,
-                           "idlType": "DOMString",
-                           "sequence": false,
-                           "generic": null,
-                           "union": false
+                            "type": null,
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": true,
+                            "union": true,
+                            "idlType": [
+                                {
+                                    "type": null,
+                                    "sequence": false,
+                                    "generic": null,
+                                    "nullable": false,
+                                    "union": false,
+                                    "idlType": "Node"
+                                },
+                                {
+                                    "type": null,
+                                    "sequence": false,
+                                    "generic": null,
+                                    "nullable": false,
+                                    "union": false,
+                                    "idlType": "DOMString"
+                                }
+                            ]
                         }
-                     ],
-                     "nullable": true,
-                     "union": true
-                  }
-               ],
-               "nullable": false,
-               "generic": null,
-               "sequence": false,
-               "union": true
+                    ]
+                },
+                "name": "test",
+                "extAttrs": []
             },
-            "name": "test",
-            "inherit": false,
-            "type": "attribute",
-            "extAttrs": [],
-            "readonly": false,
-            "stringifier": false,
-            "static": false
-         },
-         {
-            "readonly": false,
-            "extAttrs": [],
-            "stringifier": false,
-            "static": false,
-            "name": "test2",
-            "idlType": {
-               "nullable": false,
-               "idlType": [
-                  {
-                     "extAttrs": [
+            {
+                "type": "attribute",
+                "static": false,
+                "stringifier": false,
+                "inherit": false,
+                "readonly": false,
+                "idlType": {
+                    "type": "attribute-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": true,
+                    "idlType": [
                         {
-                           "name": "EnforceRange",
-                           "arguments": null,
-                           "type": "extended-attribute",
-                           "rhs": null
+                            "type": null,
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": false,
+                            "union": false,
+                            "idlType": "long",
+                            "extAttrs": [
+                                {
+                                    "name": "EnforceRange",
+                                    "arguments": null,
+                                    "type": "extended-attribute",
+                                    "rhs": null
+                                }
+                            ]
+                        },
+                        {
+                            "type": null,
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": false,
+                            "union": false,
+                            "idlType": "Date"
                         }
-                     ],
-                     "nullable": false,
-                     "idlType": "long",
-                     "generic": null,
-                     "sequence": false,
-                     "union": false
-                  },
-                  {
-                     "union": false,
-                     "sequence": false,
-                     "generic": null,
-                     "idlType": "Date",
-                     "nullable": false
-                  }
-               ],
-               "generic": null,
-               "sequence": false,
-               "union": true
-            },
-            "inherit": false,
-            "type": "attribute"
-         }
-      ],
-      "inheritance": null,
-      "name": "Union",
-      "extAttrs": [],
-      "type": "interface"
-   }
+                    ]
+                },
+                "name": "test2",
+                "extAttrs": []
+            }
+        ],
+        "inheritance": null,
+        "extAttrs": []
+    }
 ]
--- 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
@@ -6,16 +6,17 @@
         "members": [
             {
                 "type": "attribute",
                 "static": false,
                 "stringifier": false,
                 "inherit": false,
                 "readonly": true,
                 "idlType": {
+                    "type": "attribute-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "unsigned long"
                 },
                 "name": "cardinality",
                 "extAttrs": []
@@ -23,29 +24,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "union",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": true,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "long"
                         },
                         "name": "ints"
                     }
@@ -55,29 +58,31 @@
             {
                 "type": "operation",
                 "getter": false,
                 "setter": false,
                 "deleter": false,
                 "static": false,
                 "stringifier": false,
                 "idlType": {
+                    "type": "return-type",
                     "sequence": false,
                     "generic": null,
                     "nullable": false,
                     "union": false,
                     "idlType": "void"
                 },
                 "name": "intersection",
                 "arguments": [
                     {
                         "optional": false,
                         "variadic": true,
                         "extAttrs": [],
                         "idlType": {
+                            "type": "argument-type",
                             "sequence": false,
                             "generic": null,
                             "nullable": false,
                             "union": false,
                             "idlType": "long"
                         },
                         "name": "ints"
                     }
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/util/acquire.js
@@ -0,0 +1,8 @@
+"use strict";
+
+const { collect } = require("./collect");
+const fs = require("fs");
+
+for (const test of collect("syntax")) {
+  fs.writeFileSync(test.jsonPath, `${JSON.stringify(test.ast, null, 4)}\n`)
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/util/collect.js
@@ -0,0 +1,59 @@
+"use strict";
+
+const wp = require("../../lib/webidl2");
+const pth = require("path");
+const fs = require("fs");
+const jdp = require("jsondiffpatch");
+
+/**
+ * Collects test items from the specified directory
+ * @param {string} base
+ */
+function* collect(base, { expectError } = {}) {
+  base = pth.join(__dirname, "..", base);
+  const dir = pth.join(base, "idl");
+  const idls = fs.readdirSync(dir)
+    .filter(it => (/\.widl$/).test(it))
+    .map(it => pth.join(dir, it));
+
+  for (const path of idls) {
+    const optFile = pth.join(base, "opt", pth.basename(path)).replace(".widl", ".json");
+    let opt;
+    if (fs.existsSync(optFile))
+      opt = JSON.parse(fs.readFileSync(optFile, "utf8"));
+
+    try {
+      const ast = wp.parse(fs.readFileSync(path, "utf8").replace(/\r\n/g, "\n"), opt);
+      yield new TestItem({ ast, path, opt });
+    }
+    catch (error) {
+      if (expectError) {
+        yield new TestItem({ path, error });
+      }
+      else {
+        throw error;
+      }
+    }
+  }
+};
+
+
+class TestItem {
+  constructor({ ast, path, error, opt }) {
+    this.ast = ast;
+    this.path = path;
+    this.error = error;
+    this.opt = opt;
+    this.jsonPath = pth.join(pth.dirname(path), "../json", pth.basename(path).replace(".widl", ".json"));
+  }
+
+  readJSON() {
+    return JSON.parse(fs.readFileSync(this.jsonPath, "utf8"));
+  }
+
+  diff(target = this.readJSON()) {
+    return jdp.diff(target, this.ast);
+  }
+}
+
+module.exports.collect = collect;
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/webidl2/test/writer.js
@@ -0,0 +1,23 @@
+"use strict";
+
+const { collect } = require("./util/collect");
+const wp = require("../lib/webidl2");
+const writer = require("../lib/writer");
+const expect = require("expect");
+const debug = true;
+
+describe("Rewrite and parses all of the IDLs to produce the same ASTs", () => {
+  for (const test of collect("syntax")) {
+    it(`should produce the same AST for ${test.path}`, () => {
+      try {
+        const diff = test.diff(wp.parse(writer.write(test.ast), test.opt));
+        if (diff && debug) console.log(JSON.stringify(diff, null, 4));
+        expect(diff).toBe(undefined);
+      }
+      catch (e) {
+        console.log(e.toString());
+        throw e;
+      }
+    });
+  }
+});