Bug 1456980 [wpt PR 10643] - Move WebAudio node constructor tests to WPT, a=testonly
authorRaymond Toy <rtoy@chromium.org>
Tue, 01 May 2018 14:58:46 +0000
changeset 416541 ff155e599e248b7e4834e7a2ff2d6f29423baca9
parent 416540 b6a3b6789d460b704ddb6fb31897aaf9b0164319
child 416542 ec73f6441af6f652a2c1e64f50c0b9d4b8e509cf
push id102808
push userjames@hoppipolla.co.uk
push dateWed, 02 May 2018 07:14:45 +0000
treeherdermozilla-inbound@37b3d10ba167 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1456980, 10643, 745778, 1028713, 554032
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 1456980 [wpt PR 10643] - Move WebAudio node constructor tests to WPT, a=testonly Automatic update from web-platform-testsMove WebAudio node constructor tests to WPT Move the constructor tests. Manually verified that Firefox either passes the tests or fails because of bugs in Firefox. Bug: 745778 Change-Id: Iee14d9c7531dc0094bac86daede5d62299c5fb93 Reviewed-on: https://chromium-review.googlesource.com/1028713 Reviewed-by: Hongchan Choi <hongchan@chromium.org> Commit-Queue: Raymond Toy <rtoy@chromium.org> Cr-Commit-Position: refs/heads/master@{#554032} -- wpt-commits: 5fa96e1b9cb116519bcb0e6bd1a5b1f532130009 wpt-pr: 10643
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/webaudio/resources/audionodeoptions.js
testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/ctor-analyser.html
testing/web-platform/tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html
testing/web-platform/tests/webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html
testing/web-platform/tests/webaudio/the-audio-api/the-channelmergernode-interface/ctor-channelmerger.html
testing/web-platform/tests/webaudio/the-audio-api/the-channelsplitternode-interface/ctor-channelsplitter.html
testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html
testing/web-platform/tests/webaudio/the-audio-api/the-convolvernode-interface/ctor-convolver.html
testing/web-platform/tests/webaudio/the-audio-api/the-delaynode-interface/ctor-delay.html
testing/web-platform/tests/webaudio/the-audio-api/the-dynamicscompressornode-interface/ctor-dynamicscompressor.html
testing/web-platform/tests/webaudio/the-audio-api/the-gainnode-interface/ctor-gain.html
testing/web-platform/tests/webaudio/the-audio-api/the-iirfilternode-interface/ctor-iirfilter.html
testing/web-platform/tests/webaudio/the-audio-api/the-offlineaudiocontext-interface/ctor-offlineaudiocontext.html
testing/web-platform/tests/webaudio/the-audio-api/the-oscillatornode-interface/ctor-oscillator.html
testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html
testing/web-platform/tests/webaudio/the-audio-api/the-stereopanner-interface/ctor-stereopanner.html
testing/web-platform/tests/webaudio/the-audio-api/the-waveshapernode-interface/ctor-waveshaper.html
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -297219,16 +297219,21 @@
      {}
     ]
    ],
    "webaudio/refresh_idl.rb": [
     [
      {}
     ]
    ],
+   "webaudio/resources/audionodeoptions.js": [
+    [
+     {}
+    ]
+   ],
    "webaudio/resources/audioparam-testing.js": [
     [
      {}
     ]
    ],
    "webaudio/resources/audit-util.js": [
     [
      {}
@@ -369140,16 +369145,22 @@
     ]
    ],
    "webaudio/idlharness.https.html": [
     [
      "/webaudio/idlharness.https.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-analysernode-interface/ctor-analyser.html": [
+    [
+     "/webaudio/the-audio-api/the-analysernode-interface/ctor-analyser.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html": [
     [
      "/webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-analysernode-interface/test-analyser-minimum.html": [
     [
@@ -369176,16 +369187,22 @@
     ]
    ],
    "webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html": [
     [
      "/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html": [
+    [
+     "/webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html": [
     [
      "/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-audionode-interface/audionode-channel-rules.html": [
     [
@@ -369488,16 +369505,22 @@
     ]
    ],
    "webaudio/the-audio-api/the-biquadfilternode-interface/biquadfilternode-basic.html": [
     [
      "/webaudio/the-audio-api/the-biquadfilternode-interface/biquadfilternode-basic.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html": [
+    [
+     "/webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-biquadfilternode-interface/no-dezippering.html": [
     [
      "/webaudio/the-audio-api/the-biquadfilternode-interface/no-dezippering.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-channelmergernode-interface/audiochannelmerger-basic.html": [
     [
@@ -369518,22 +369541,34 @@
     ]
    ],
    "webaudio/the-audio-api/the-channelmergernode-interface/audiochannelmerger-input.html": [
     [
      "/webaudio/the-audio-api/the-channelmergernode-interface/audiochannelmerger-input.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-channelmergernode-interface/ctor-channelmerger.html": [
+    [
+     "/webaudio/the-audio-api/the-channelmergernode-interface/ctor-channelmerger.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-channelsplitternode-interface/audiochannelsplitter.html": [
     [
      "/webaudio/the-audio-api/the-channelsplitternode-interface/audiochannelsplitter.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-channelsplitternode-interface/ctor-channelsplitter.html": [
+    [
+     "/webaudio/the-audio-api/the-channelsplitternode-interface/ctor-channelsplitter.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html": [
     [
      "/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-onended.html": [
     [
@@ -369542,16 +369577,22 @@
     ]
    ],
    "webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-output.html": [
     [
      "/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-output.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html": [
+    [
+     "/webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-constantsourcenode-interface/test-constantsourcenode.html": [
     [
      "/webaudio/the-audio-api/the-constantsourcenode-interface/test-constantsourcenode.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-convolvernode-interface/convolution-mono-mono.html": [
     [
@@ -369590,16 +369631,28 @@
     ]
    ],
    "webaudio/the-audio-api/the-convolvernode-interface/convolver-setBuffer-null.html": [
     [
      "/webaudio/the-audio-api/the-convolvernode-interface/convolver-setBuffer-null.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-convolvernode-interface/ctor-convolver.html": [
+    [
+     "/webaudio/the-audio-api/the-convolvernode-interface/ctor-convolver.html",
+     {}
+    ]
+   ],
+   "webaudio/the-audio-api/the-delaynode-interface/ctor-delay.html": [
+    [
+     "/webaudio/the-audio-api/the-delaynode-interface/ctor-delay.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-delaynode-interface/delaynode-max-default-delay.html": [
     [
      "/webaudio/the-audio-api/the-delaynode-interface/delaynode-max-default-delay.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-delaynode-interface/delaynode-max-nondefault-delay.html": [
     [
@@ -369632,22 +369685,34 @@
     ]
    ],
    "webaudio/the-audio-api/the-delaynode-interface/no-dezippering.html": [
     [
      "/webaudio/the-audio-api/the-delaynode-interface/no-dezippering.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-dynamicscompressornode-interface/ctor-dynamicscompressor.html": [
+    [
+     "/webaudio/the-audio-api/the-dynamicscompressornode-interface/ctor-dynamicscompressor.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-dynamicscompressornode-interface/dynamicscompressor-basic.html": [
     [
      "/webaudio/the-audio-api/the-dynamicscompressornode-interface/dynamicscompressor-basic.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-gainnode-interface/ctor-gain.html": [
+    [
+     "/webaudio/the-audio-api/the-gainnode-interface/ctor-gain.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-gainnode-interface/gain-basic.html": [
     [
      "/webaudio/the-audio-api/the-gainnode-interface/gain-basic.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-gainnode-interface/gain.html": [
     [
@@ -369662,16 +369727,22 @@
     ]
    ],
    "webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html": [
     [
      "/webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-iirfilternode-interface/ctor-iirfilter.html": [
+    [
+     "/webaudio/the-audio-api/the-iirfilternode-interface/ctor-iirfilter.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-iirfilternode-interface/iirfilter-basic.html": [
     [
      "/webaudio/the-audio-api/the-iirfilternode-interface/iirfilter-basic.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-iirfilternode-interface/iirfilter-getFrequencyResponse.html": [
     [
@@ -369692,22 +369763,40 @@
     ]
    ],
    "webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html": [
     [
      "/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-offlineaudiocontext-interface/ctor-offlineaudiocontext.html": [
+    [
+     "/webaudio/the-audio-api/the-offlineaudiocontext-interface/ctor-offlineaudiocontext.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-offlineaudiocontext-interface/current-time-block-size.html": [
     [
      "/webaudio/the-audio-api/the-offlineaudiocontext-interface/current-time-block-size.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-oscillatornode-interface/ctor-oscillator.html": [
+    [
+     "/webaudio/the-audio-api/the-oscillatornode-interface/ctor-oscillator.html",
+     {}
+    ]
+   ],
+   "webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html": [
+    [
+     "/webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-pannernode-interface/distance-exponential.html": [
     [
      "/webaudio/the-audio-api/the-pannernode-interface/distance-exponential.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-pannernode-interface/distance-inverse.html": [
     [
@@ -369770,16 +369859,22 @@
     ]
    ],
    "webaudio/the-audio-api/the-pannernode-interface/test-pannernode-automation.html": [
     [
      "/webaudio/the-audio-api/the-pannernode-interface/test-pannernode-automation.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-stereopanner-interface/ctor-stereopanner.html": [
+    [
+     "/webaudio/the-audio-api/the-stereopanner-interface/ctor-stereopanner.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-stereopanner-interface/no-dezippering.html": [
     [
      "/webaudio/the-audio-api/the-stereopanner-interface/no-dezippering.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-stereopanner-interface/stereopannernode-basic.html": [
     [
@@ -369788,16 +369883,22 @@
     ]
    ],
    "webaudio/the-audio-api/the-stereopanner-interface/stereopannernode-panning.html": [
     [
      "/webaudio/the-audio-api/the-stereopanner-interface/stereopannernode-panning.html",
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-waveshapernode-interface/ctor-waveshaper.html": [
+    [
+     "/webaudio/the-audio-api/the-waveshapernode-interface/ctor-waveshaper.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html": [
     [
      "/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html",
      {}
     ]
    ],
    "webaudio/the-audio-api/the-waveshapernode-interface/waveshaper-copy-curve.html": [
     [
@@ -608969,16 +609070,20 @@
   "webaudio/js/helpers.js": [
    "3cb468605c1fa8e5005bc8552b15f7a37ee9b935",
    "support"
   ],
   "webaudio/refresh_idl.rb": [
    "9ef52c13448d19b241b40a5c81f4a0480c05c5de",
    "support"
   ],
+  "webaudio/resources/audionodeoptions.js": [
+   "d7712311bddd23e171e7e1f024aec0a565b08a13",
+   "support"
+  ],
   "webaudio/resources/audioparam-testing.js": [
    "2855fbee30e629ea397166911b9bcdec74bd4fdf",
    "support"
   ],
   "webaudio/resources/audit-util.js": [
    "4405458b8f8bdc621c95c1d9ec1c1ad4e6002f1e",
    "support"
   ],
@@ -609033,16 +609138,20 @@
   "webaudio/resources/stereopanner-testing.js": [
    "dc02b4fad40f381d924db447a3d955e4455fd561",
    "support"
   ],
   "webaudio/the-audio-api/the-analysernode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-analysernode-interface/ctor-analyser.html": [
+   "7e35ac29f00d39c84230535212c0b9ea081951d3",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html": [
    "e2320e33ef1df0155d5fcf536550e0e398b15407",
    "testharness"
   ],
   "webaudio/the-audio-api/the-analysernode-interface/test-analyser-minimum.html": [
    "26282412113f6298a90a2cac963a2b0de03ef43d",
    "testharness"
   ],
@@ -609065,16 +609174,20 @@
   "webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html": [
    "0ef05c242d8f987d521c0e9ce474d0f9a46bee28",
    "testharness"
   ],
   "webaudio/the-audio-api/the-audiobuffersourcenode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html": [
+   "ce84d25460435564021a13dc9e26384bc30e9d96",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-audiocontext-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webaudio/the-audio-api/the-audiodestinationnode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
@@ -609345,16 +609458,20 @@
   "webaudio/the-audio-api/the-biquadfilternode-interface/biquad-tail.html": [
    "e15e696492076d522c1052ae890b37f52e7bd27b",
    "testharness"
   ],
   "webaudio/the-audio-api/the-biquadfilternode-interface/biquadfilternode-basic.html": [
    "f24a473f695c2d10788ba7d50728259a08ed53c8",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html": [
+   "475916d4aba810c017c385d98d51d353ad0fc561",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-biquadfilternode-interface/no-dezippering.html": [
    "348376a643b765700342e9620e1346d432a28131",
    "testharness"
   ],
   "webaudio/the-audio-api/the-channelmergernode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
@@ -609369,36 +609486,48 @@
   "webaudio/the-audio-api/the-channelmergernode-interface/audiochannelmerger-input-non-default.html": [
    "89c8356eeed96c06eca2c904c22047dd02da4f3b",
    "testharness"
   ],
   "webaudio/the-audio-api/the-channelmergernode-interface/audiochannelmerger-input.html": [
    "250c35e36dda600c30554024cbd500a37180292a",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-channelmergernode-interface/ctor-channelmerger.html": [
+   "72bfba4cbca1b4d3e7692ef236afb905f852fadd",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-channelsplitternode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webaudio/the-audio-api/the-channelsplitternode-interface/audiochannelsplitter.html": [
    "80cfd321970b37df7995d6e0d262a2c008e6e10c",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-channelsplitternode-interface/ctor-channelsplitter.html": [
+   "743fd6af6f67958f67f4a63cef432515518edf41",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html": [
    "d60c7c7c6d9236f773199a213bef6b1103e02e2e",
    "testharness"
   ],
   "webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-onended.html": [
    "10f6b84a4c8de1a8b689cc443f2526b0455a4d27",
    "testharness"
   ],
   "webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-output.html": [
    "ce90b4d7ca5840abdc830d734df26028958fadd7",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html": [
+   "1fa8892c98ce5f979a08294a838b3b91ce11a3a3",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-constantsourcenode-interface/test-constantsourcenode.html": [
    "711b3f183d847e437a4c332f33054cc5a648fd22",
    "testharness"
   ],
   "webaudio/the-audio-api/the-convolvernode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
@@ -609425,20 +609554,28 @@
   "webaudio/the-audio-api/the-convolvernode-interface/convolver-response-4-chan.html": [
    "8fac11e0ecfa8bfb9b49d68d0792793f44e94ad4",
    "testharness"
   ],
   "webaudio/the-audio-api/the-convolvernode-interface/convolver-setBuffer-null.html": [
    "f32f5acdf031b1a2b32bc37324b105d1df7c5fdb",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-convolvernode-interface/ctor-convolver.html": [
+   "70f49ae8525bd998d3b51bada7a296ba4cef03e5",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-delaynode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-delaynode-interface/ctor-delay.html": [
+   "473c5e05ab6ee4930de9e3a3ec47075af7e9650d",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-delaynode-interface/delaynode-max-default-delay.html": [
    "c732635549f5eab61f8bdce05b27f0f3e8a3f6c2",
    "testharness"
   ],
   "webaudio/the-audio-api/the-delaynode-interface/delaynode-max-nondefault-delay.html": [
    "8c1a46ae95f921d78a59473c6f1f5d12315f07e8",
    "testharness"
   ],
@@ -609461,24 +609598,32 @@
   "webaudio/the-audio-api/the-delaynode-interface/no-dezippering.html": [
    "96b405fd00ee657194de348ea46b263ba43f98a4",
    "testharness"
   ],
   "webaudio/the-audio-api/the-dynamicscompressornode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-dynamicscompressornode-interface/ctor-dynamicscompressor.html": [
+   "6338104e8199673ff7de6f41d310b79a2ee51f04",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-dynamicscompressornode-interface/dynamicscompressor-basic.html": [
    "6ceaf50b8cacdfa246bc997f2c8e46aefd789659",
    "testharness"
   ],
   "webaudio/the-audio-api/the-gainnode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-gainnode-interface/ctor-gain.html": [
+   "3c77f0ac735a224fa6d905f62585beba39643393",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-gainnode-interface/gain-basic.html": [
    "70165c60c482d6507670af965756f639e7b3ba78",
    "testharness"
   ],
   "webaudio/the-audio-api/the-gainnode-interface/gain-expected.wav": [
    "823f7ae1a5f5eb0c630e7d1881c50a1f710f9350",
    "support"
   ],
@@ -609489,16 +609634,20 @@
   "webaudio/the-audio-api/the-gainnode-interface/no-dezippering.html": [
    "2205ec8f56472bd45e102cf57f10b4532b18a554",
    "testharness"
   ],
   "webaudio/the-audio-api/the-gainnode-interface/test-gainnode.html": [
    "bf2de43e568c79b96fd5b0602e26346c483162a5",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-iirfilternode-interface/ctor-iirfilter.html": [
+   "3627d5b4a447a62de6c6a6f10556fa9f9dec1700",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-iirfilternode-interface/iirfilter-basic.html": [
    "176168861bc667b2b05312dbae48f76f7f90d791",
    "testharness"
   ],
   "webaudio/the-audio-api/the-iirfilternode-interface/iirfilter-getFrequencyResponse.html": [
    "1f1cc3004a65acf09667d3a21150f9ce052f71fb",
    "testharness"
   ],
@@ -609525,28 +609674,40 @@
   "webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webaudio/the-audio-api/the-offlineaudiocontext-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-offlineaudiocontext-interface/ctor-offlineaudiocontext.html": [
+   "4264798e9e64d30c72f9f0577a9648efa2d0a50a",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-offlineaudiocontext-interface/current-time-block-size.html": [
    "d0b1fefa6c0f75c0666cd5b7e8305099e9925d62",
    "testharness"
   ],
   "webaudio/the-audio-api/the-oscillatornode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-oscillatornode-interface/ctor-oscillator.html": [
+   "53df9d36a96c61a6ce9215cbc2830783e26c91be",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-pannernode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html": [
+   "2b59d21a54b2216c1171a6ba2c7809291955a8af",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-pannernode-interface/distance-exponential.html": [
    "c1c94753ebcd1930e326d73c085e6c3197967cd5",
    "testharness"
   ],
   "webaudio/the-audio-api/the-pannernode-interface/distance-inverse.html": [
    "400d2a373de3e4255279930fca2ec559aed19688",
    "testharness"
   ],
@@ -609593,32 +609754,40 @@
   "webaudio/the-audio-api/the-periodicwave-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webaudio/the-audio-api/the-scriptprocessornode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-stereopanner-interface/ctor-stereopanner.html": [
+   "1908ffc477d8c16b81ab371f5b9dbca46cc16a83",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-stereopanner-interface/no-dezippering.html": [
    "b3525a2c459125281196201216417c39030e79a8",
    "testharness"
   ],
   "webaudio/the-audio-api/the-stereopanner-interface/stereopannernode-basic.html": [
    "5654219a5816d603260c33b4d72030e89e8c63d9",
    "testharness"
   ],
   "webaudio/the-audio-api/the-stereopanner-interface/stereopannernode-panning.html": [
    "4f49a7d5726c922676d350613679c9c441ff6c65",
    "testharness"
   ],
   "webaudio/the-audio-api/the-waveshapernode-interface/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "webaudio/the-audio-api/the-waveshapernode-interface/ctor-waveshaper.html": [
+   "80b585554acf22f357264e3a024d2159fd184f13",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html": [
    "f88431616d6a8084a3434c1606e3543178d019fb",
    "testharness"
   ],
   "webaudio/the-audio-api/the-waveshapernode-interface/waveshaper-copy-curve.html": [
    "28cc01fdd27a3ff88f2e886bc625d4dfd15db742",
    "testharness"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/resources/audionodeoptions.js
@@ -0,0 +1,251 @@
+// Test that constructor for the node with name |nodeName| handles the
+// various possible values for channelCount, channelCountMode, and
+// channelInterpretation.
+
+// The |should| parameter is the test function from new |Audit|.
+function testAudioNodeOptions(should, context, nodeName, expectedNodeOptions) {
+  if (expectedNodeOptions === undefined)
+    expectedNodeOptions = {};
+  let node;
+
+  // Test that we can set channelCount and that errors are thrown for
+  // invalid values
+  let testChannelCount = 17;
+  if (expectedNodeOptions.channelCount) {
+    testChannelCount = expectedNodeOptions.channelCount.value;
+  }
+  should(
+      () => {
+        node = new window[nodeName](
+            context, Object.assign({}, expectedNodeOptions.additionalOptions, {
+              channelCount: testChannelCount
+            }));
+      },
+      'new ' + nodeName + '(c, {channelCount: ' + testChannelCount + '}}')
+      .notThrow();
+  should(node.channelCount, 'node.channelCount').beEqualTo(testChannelCount);
+
+  if (expectedNodeOptions.channelCount &&
+      expectedNodeOptions.channelCount.isFixed) {
+    // The channel count is fixed.  Verify that we throw an error if
+    // we try to change it. Arbitrarily set the count to be one more
+    // than the expected value.
+    testChannelCount = expectedNodeOptions.channelCount.value + 1;
+    should(
+        () => {
+          node = new window[nodeName](
+              context,
+              Object.assign(
+                  {}, expectedNodeOptions.additionalOptions,
+                  {channelCount: testChannelCount}));
+        },
+        'new ' + nodeName + '(c, {channelCount: ' + testChannelCount + '}}')
+        .throw(expectedNodeOptions.channelCount.errorType || 'TypeError');
+  } else {
+    // The channel count is not fixed.  Try to set the count to invalid
+    // values and make sure an error is thrown.
+    let errorType = 'NotSupportedError';
+
+    [0, 99].forEach(testValue => {
+      should(() => {
+        node = new window[nodeName](
+            context, Object.assign({}, expectedNodeOptions.additionalOptions, {
+              channelCount: testValue
+            }));
+      }, `new ${nodeName}(c, {channelCount: ${testValue}})`).throw(errorType);
+    });
+  }
+
+  // Test channelCountMode
+  let testChannelCountMode = 'max';
+  if (expectedNodeOptions.channelCountMode) {
+    testChannelCountMode = expectedNodeOptions.channelCountMode.value;
+  }
+  should(
+      () => {
+        node = new window[nodeName](
+            context, Object.assign({}, expectedNodeOptions.additionalOptions, {
+              channelCountMode: testChannelCountMode
+            }));
+      },
+      'new ' + nodeName + '(c, {channelCountMode: "' + testChannelCountMode +
+          '"}')
+      .notThrow();
+  should(node.channelCountMode, 'node.channelCountMode')
+      .beEqualTo(testChannelCountMode);
+
+  if (expectedNodeOptions.channelCountMode &&
+      expectedNodeOptions.channelCountMode.isFixed) {
+    // Channel count mode is fixed.  Test setting to something else throws.
+    ['max', 'clamped-max', 'explicit'].forEach(testValue => {
+      if (testValue !== expectedNodeOptions.channelCountMode.value) {
+        should(
+            () => {
+              node = new window[nodeName](
+                  context,
+                  Object.assign(
+                      {}, expectedNodeOptions.additionalOptions,
+                      {channelCountMode: testValue}));
+            },
+            `new ${nodeName}(c, {channelCountMode: "${testValue}"})`)
+            .throw(expectedNodeOptions.channelCountMode.errorType);
+      }
+    });
+  } else {
+    // Mode is not fixed. Verify that we can set the mode to all valid
+    // values, and that we throw for invalid values.
+
+    let testValues = ['max', 'clamped-max', 'explicit'];
+
+    testValues.forEach(testValue => {
+      should(() => {
+        node = new window[nodeName](
+            context, Object.assign({}, expectedNodeOptions.additionalOptions, {
+              channelCountMode: testValue
+            }));
+      }, `new ${nodeName}(c, {channelCountMode: "${testValue}"})`).notThrow();
+      should(
+          node.channelCountMode, 'node.channelCountMode after valid setter')
+          .beEqualTo(testValue);
+
+    });
+
+    should(
+        () => {
+          node = new window[nodeName](
+              context,
+              Object.assign(
+                  {}, expectedNodeOptions.additionalOptions,
+                  {channelCountMode: 'foobar'}));
+        },
+        'new ' + nodeName + '(c, {channelCountMode: "foobar"}')
+        .throw('TypeError');
+    should(node.channelCountMode, 'node.channelCountMode after invalid setter')
+        .beEqualTo(testValues[testValues.length - 1]);
+  }
+
+  // Test channelInterpretation
+  if (expectedNodeOptions.channelInterpretation &&
+      expectedNodeOptions.channelInterpretation.isFixed) {
+    // The channel interpretation is fixed.  Verify that we throw an
+    // error if we try to change it.
+    ['speakers', 'discrete'].forEach(testValue => {
+      if (testValue !== expectedNodeOptions.channelInterpretation.value) {
+        should(
+            () => {
+              node = new window[nodeName](
+                  context,
+                  Object.assign(
+                      {}, expectedNodeOptions.additionOptions,
+                      {channelInterpretation: testValue}));
+            },
+            `new ${nodeName}(c, {channelInterpretation: "${testValue}"})`)
+            .throw(expectedNodeOptions.channelInterpretation.errorType);
+      }
+    });
+  } else {
+    // Channel interpretation is not fixed. Verify that we can set it
+    // to all possible values.
+    should(
+        () => {
+          node = new window[nodeName](
+              context,
+              Object.assign(
+                  {}, expectedNodeOptions.additionalOptions,
+                  {channelInterpretation: 'speakers'}));
+        },
+        'new ' + nodeName + '(c, {channelInterpretation: "speakers"})')
+        .notThrow();
+    should(node.channelInterpretation, 'node.channelInterpretation')
+        .beEqualTo('speakers');
+
+    should(
+        () => {
+          node = new window[nodeName](
+              context,
+              Object.assign(
+                  {}, expectedNodeOptions.additionalOptions,
+                  {channelInterpretation: 'discrete'}));
+        },
+        'new ' + nodeName + '(c, {channelInterpretation: "discrete"})')
+        .notThrow();
+    should(node.channelInterpretation, 'node.channelInterpretation')
+        .beEqualTo('discrete');
+
+    should(
+        () => {
+          node = new window[nodeName](
+              context,
+              Object.assign(
+                  {}, expectedNodeOptions.additionalOptions,
+                  {channelInterpretation: 'foobar'}));
+        },
+        'new ' + nodeName + '(c, {channelInterpretation: "foobar"})')
+        .throw('TypeError');
+    should(
+        node.channelInterpretation,
+        'node.channelInterpretation after invalid setter')
+        .beEqualTo('discrete');
+  }
+}
+
+function initializeContext(should) {
+  let c;
+  should(() => {
+    c = new OfflineAudioContext(1, 1, 48000);
+  }, 'context = new OfflineAudioContext(...)').notThrow();
+
+  return c;
+}
+
+function testInvalidConstructor(should, name, context) {
+  should(() => {
+    new window[name]();
+  }, 'new ' + name + '()').throw('TypeError');
+  should(() => {
+    new window[name](1);
+  }, 'new ' + name + '(1)').throw('TypeError');
+  should(() => {
+    new window[name](context, 42);
+  }, 'new ' + name + '(context, 42)').throw('TypeError');
+}
+
+function testDefaultConstructor(should, name, context, options) {
+  let node;
+
+  let message = options.prefix + ' = new ' + name + '(context';
+  if (options.constructorOptions)
+    message += ', ' + JSON.stringify(options.constructorOptions);
+  message += ')'
+
+  should(() => {
+    node = new window[name](context, options.constructorOptions);
+  }, message).notThrow();
+
+  should(node instanceof window[name], options.prefix + ' instanceof ' + name)
+      .beEqualTo(true);
+  should(node.numberOfInputs, options.prefix + '.numberOfInputs')
+      .beEqualTo(options.numberOfInputs);
+  should(node.numberOfOutputs, options.prefix + '.numberOfOutputs')
+      .beEqualTo(options.numberOfOutputs);
+  should(node.channelCount, options.prefix + '.channelCount')
+      .beEqualTo(options.channelCount);
+  should(node.channelCountMode, options.prefix + '.channelCountMode')
+      .beEqualTo(options.channelCountMode);
+  should(node.channelInterpretation, options.prefix + '.channelInterpretation')
+      .beEqualTo(options.channelInterpretation);
+
+  return node;
+}
+
+function testDefaultAttributes(should, node, prefix, items) {
+  items.forEach((item) => {
+    let attr = node[item.name];
+    if (attr instanceof AudioParam) {
+      should(attr.value, prefix + '.' + item.name + '.value')
+          .beEqualTo(item.value);
+    } else {
+      should(attr, prefix + '.' + item.name).beEqualTo(item.value);
+    }
+  });
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/ctor-analyser.html
@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: AnalyserNode
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'AnalyserNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'AnalyserNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 1,
+          channelCountMode: 'max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(should, node, prefix, [
+          {name: 'fftSize', value: 2048},
+          {name: 'frequencyBinCount', value: 1024},
+          {name: 'minDecibels', value: -100}, {name: 'maxDecibels', value: -30},
+          {name: 'smoothingTimeConstant', value: 0.8}
+        ]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'AnalyserNode');
+        task.done();
+      });
+
+      audit.define('constructor with options', (task, should) => {
+        let options = {
+          fftSize: 32,
+          maxDecibels: 1,
+          minDecibels: -13,
+          // Choose a value that can be represented the same as a float and as a
+          // double.
+          smoothingTimeConstant: 0.125
+        };
+
+        let node;
+        should(
+            () => {
+              node = new AnalyserNode(context, options);
+            },
+            'node1 = new AnalyserNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        should(node instanceof AnalyserNode, 'node1 instanceof AnalyserNode')
+            .beEqualTo(true);
+        should(node.fftSize, 'node1.fftSize').beEqualTo(options.fftSize);
+        should(node.maxDecibels, 'node1.maxDecibels')
+            .beEqualTo(options.maxDecibels);
+        should(node.minDecibels, 'node1.minDecibels')
+            .beEqualTo(options.minDecibels);
+        should(node.smoothingTimeConstant, 'node1.smoothingTimeConstant')
+            .beEqualTo(options.smoothingTimeConstant);
+
+        task.done();
+      });
+
+      audit.define('construct invalid options', (task, should) => {
+        let node;
+
+        should(
+            () => {
+              node = new AnalyserNode(context, {fftSize: 33});
+            },
+            'node = new AnalyserNode(c, { fftSize: 33 })')
+            .throw('IndexSizeError');
+        should(
+            () => {
+              node = new AnalyserNode(context, {maxDecibels: -500});
+            },
+            'node = new AnalyserNode(c, { maxDecibels: -500 })')
+            .throw('IndexSizeError');
+        should(
+            () => {
+              node = new AnalyserNode(context, {minDecibels: -10});
+            },
+            'node = new AnalyserNode(c, { minDecibels: -10 })')
+            .throw('IndexSizeError');
+        should(
+            () => {
+              node = new AnalyserNode(context, {smoothingTimeConstant: 2});
+            },
+            'node = new AnalyserNode(c, { smoothingTimeConstant: 2 })')
+            .throw('IndexSizeError');
+        should(function() {
+          node = new AnalyserNode(context, {frequencyBinCount: 33});
+        }, 'node = new AnalyserNode(c, { frequencyBinCount: 33 })').notThrow();
+        should(node.frequencyBinCount, 'node.frequencyBinCount')
+            .beEqualTo(1024);
+
+        task.done();
+      });
+
+      audit.define('setting min/max', (task, should) => {
+        let node;
+
+        // Recall the default values of minDecibels and maxDecibels are -100,
+        // and -30, respectively.  Setting both values in the constructor should
+        // not signal an error in any of the following cases.
+        let options = {minDecibels: -10, maxDecibels: 20};
+        should(
+            () => {
+              node = new AnalyserNode(context, options);
+            },
+            'node = new AnalyserNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        options = {maxDecibels: 20, minDecibels: -10};
+        should(
+            () => {
+              node = new AnalyserNode(context, options);
+            },
+            'node = new AnalyserNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        options = {minDecibels: -200, maxDecibels: -150};
+        should(
+            () => {
+              node = new AnalyserNode(context, options);
+            },
+            'node = new AnalyserNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        options = {maxDecibels: -150, minDecibels: -200};
+        should(
+            () => {
+              node = new AnalyserNode(context, options);
+            },
+            'node = new AnalyserNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        // But these should signal because minDecibel > maxDecibel
+        options = {maxDecibels: -150, minDecibels: -10};
+        should(
+            () => {
+              node = new AnalyserNode(context, options);
+            },
+            'node = new AnalyserNode(c, ' + JSON.stringify(options) + ')')
+            .throw('IndexSizeError');
+
+        options = {minDecibels: -10, maxDecibels: -150};
+        should(
+            () => {
+              node = new AnalyserNode(context, options);
+            },
+            'node = new AnalyserNode(c, ' + JSON.stringify(options) + ')')
+            .throw('IndexSizeError');
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/ctor-audiobuffersource.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: AudioBufferSource
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'AudioBufferSourceNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node =
+            testDefaultConstructor(should, 'AudioBufferSourceNode', context, {
+              prefix: prefix,
+              numberOfInputs: 0,
+              numberOfOutputs: 1,
+              channelCount: 2,
+              channelCountMode: 'max',
+              channelInterpretation: 'speakers'
+            });
+
+        testDefaultAttributes(should, node, prefix, [
+          {name: 'buffer', value: null},
+          {name: 'detune', value: 0},
+          {name: 'loop', value: false},
+          {name: 'loopEnd', value: 0.0},
+          {name: 'loopStart', value: 0.0},
+          {name: 'playbackRate', value: 1.0},
+        ]);
+
+        task.done();
+      });
+
+      audit.define('nullable buffer', (task, should) => {
+        let node;
+        let options = {buffer: null};
+
+        should(
+            () => {
+              node = new AudioBufferSourceNode(context, options);
+            },
+            'node1 = new AudioBufferSourceNode(c, ' + JSON.stringify(options))
+            .notThrow();
+
+        should(node.buffer, 'node1.buffer').beEqualTo(null);
+
+        task.done();
+      });
+
+      audit.define('constructor options', (task, should) => {
+        let node;
+        let buffer = context.createBuffer(2, 1000, context.sampleRate);
+
+        let options = {
+          buffer: buffer,
+          detune: .5,
+          loop: true,
+          loopEnd: (buffer.length / 2) / context.sampleRate,
+          loopStart: 5 / context.sampleRate,
+          playbackRate: .75
+        };
+
+        let message = 'node = new AudioBufferSourceNode(c, ' +
+            JSON.stringify(options) + ')';
+
+        should(() => {
+          node = new AudioBufferSourceNode(context, options);
+        }, message).notThrow();
+
+        // Use the factory method to create an equivalent node and compare the
+        // results from the constructor against this node.
+        let factoryNode = context.createBufferSource();
+        factoryNode.buffer = options.buffer;
+        factoryNode.detune.value = options.detune;
+        factoryNode.loop = options.loop;
+        factoryNode.loopEnd = options.loopEnd;
+        factoryNode.loopStart = options.loopStart;
+        factoryNode.playbackRate.value = options.playbackRate;
+
+        should(node.buffer === buffer, 'node2.buffer === buffer')
+            .beEqualTo(true);
+        should(node.detune.value, 'node2.detune.value')
+            .beEqualTo(factoryNode.detune.value);
+        should(node.loop, 'node2.loop').beEqualTo(factoryNode.loop);
+        should(node.loopEnd, 'node2.loopEnd').beEqualTo(factoryNode.loopEnd);
+        should(node.loopStart, 'node2.loopStart')
+            .beEqualTo(factoryNode.loopStart);
+        should(node.playbackRate.value, 'node2.playbackRate.value')
+            .beEqualTo(factoryNode.playbackRate.value);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: BiquadFilter
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'BiquadFilterNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'BiquadFilterNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(should, node, prefix, [
+          {name: 'type', value: 'lowpass'}, {name: 'Q', value: 1},
+          {name: 'detune', value: 0}, {name: 'frequency', value: 350},
+          {name: 'gain', value: 0.0}
+        ]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'BiquadFilterNode');
+        task.done();
+      });
+
+      audit.define('construct with options', (task, should) => {
+        let node;
+        let options = {
+          type: 'highpass',
+          frequency: 512,
+          detune: 1,
+          Q: 5,
+          gain: 3,
+        };
+
+        should(
+            () => {
+              node = new BiquadFilterNode(context, options);
+            },
+            'node = new BiquadFilterNode(..., ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        // Test that attributes are set according to the option values.
+        should(node.type, 'node.type').beEqualTo(options.type);
+        should(node.frequency.value, 'node.frequency.value')
+            .beEqualTo(options.frequency);
+        should(node.detune.value, 'node.detuen.value')
+            .beEqualTo(options.detune);
+        should(node.Q.value, 'node.Q.value').beEqualTo(options.Q);
+        should(node.gain.value, 'node.gain.value').beEqualTo(options.gain);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-channelmergernode-interface/ctor-channelmerger.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: ChannelMerger
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'ChannelMergerNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node =
+            testDefaultConstructor(should, 'ChannelMergerNode', context, {
+              prefix: prefix,
+              numberOfInputs: 6,
+              numberOfOutputs: 1,
+              channelCount: 1,
+              channelCountMode: 'explicit',
+              channelInterpretation: 'speakers'
+            });
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'ChannelMergerNode', {
+          channelCount:
+              {value: 1, isFixed: true, errorType: 'InvalidStateError'},
+          channelCountMode: {
+            value: 'explicit',
+            isFixed: true,
+            errorType: 'InvalidStateError'
+          }
+        });
+        task.done();
+      });
+
+      audit.define('constructor options', (task, should) => {
+        let node;
+        let options = {
+          numberOfInputs: 3,
+          numberOfOutputs: 9,
+          channelInterpretation: 'discrete'
+        };
+
+        should(
+            () => {
+              node = new ChannelMergerNode(context, options);
+            },
+            'node1 = new ChannelMergerNode(context, ' +
+                JSON.stringify(options) + ')')
+            .notThrow();
+
+        should(node.numberOfInputs, 'node1.numberOfInputs')
+            .beEqualTo(options.numberOfInputs);
+        should(node.numberOfOutputs, 'node1.numberOfOutputs').beEqualTo(1);
+        should(node.channelInterpretation, 'node1.channelInterpretation')
+            .beEqualTo(options.channelInterpretation);
+
+        options = {numberOfInputs: 99};
+        should(
+            () => {
+              node = new ChannelMergerNode(context, options);
+            },
+            'new ChannelMergerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('IndexSizeError');
+
+        options = {channelCount: 3};
+        should(
+            () => {
+              node = new ChannelMergerNode(context, options);
+            },
+            'new ChannelMergerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('InvalidStateError');
+
+        options = {channelCountMode: 'max'};
+        should(
+            () => {
+              node = new ChannelMergerNode(context, options);
+            },
+            'new ChannelMergerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('InvalidStateError');
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-channelsplitternode-interface/ctor-channelsplitter.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: ChannelSplitter
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'ChannelSplitterNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        testDefaultConstructor(should, 'ChannelSplitterNode', context, {
+          prefix: 'node0',
+          numberOfInputs: 1,
+          numberOfOutputs: 6,
+          channelCount: 6,
+          channelCountMode: 'explicit',
+          channelInterpretation: 'discrete'
+        });
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'ChannelSplitterNode', {
+          channelCount:
+              {value: 6, isFixed: true, errorType: 'InvalidStateError'},
+          channelCountMode: {
+            value: 'explicit',
+            isFixed: true,
+          },
+          channelInterpretation: {
+            value: 'discrete',
+            isFixed: true,
+            errorType: 'InvalidStateError'
+          },
+        });
+        task.done();
+      });
+
+      audit.define('constructor options', (task, should) => {
+        let node;
+        let options = {
+          numberOfInputs: 3,
+          numberOfOutputs: 9,
+          channelInterpretation: 'discrete'
+        };
+
+        should(
+            () => {
+              node = new ChannelSplitterNode(context, options);
+            },
+            'node1 = new ChannelSplitterNode(context, ' +
+                JSON.stringify(options) + ')')
+            .notThrow();
+
+        should(node.numberOfInputs, 'node1.numberOfInputs').beEqualTo(1);
+        should(node.numberOfOutputs, 'node1.numberOfOutputs')
+            .beEqualTo(options.numberOfOutputs);
+        should(node.channelInterpretation, 'node1.channelInterpretation')
+            .beEqualTo(options.channelInterpretation);
+
+        options = {numberOfOutputs: 99};
+        should(
+            () => {
+              node = new ChannelSplitterNode(context, options);
+            },
+            'new ChannelSplitterNode(c, ' + JSON.stringify(options) + ')')
+            .throw('IndexSizeError');
+
+        options = {channelCount: 3};
+        should(
+            () => {
+              node = new ChannelSplitterNode(context, options);
+            },
+            'new ChannelSplitterNode(c, ' + JSON.stringify(options) + ')')
+            .throw('InvalidStateError');
+
+        options = {channelCountMode: 'max'};
+        should(
+            () => {
+              node = new ChannelSplitterNode(context, options);
+            },
+            'new ChannelSplitterNode(c, ' + JSON.stringify(options) + ')')
+            .throw('InvalidStateError');
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: ConstantSource
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'ConstantSourceNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node =
+            testDefaultConstructor(should, 'ConstantSourceNode', context, {
+              prefix: prefix,
+              numberOfInputs: 0,
+              numberOfOutputs: 1,
+              channelCount: 2,
+              channelCountMode: 'max',
+              channelInterpretation: 'speakers'
+            });
+
+        testDefaultAttributes(
+            should, node, prefix, [{name: 'offset', value: 1}]);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-convolvernode-interface/ctor-convolver.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: Convolver
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'ConvolverNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'ConvolverNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'clamped-max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(
+            should, node, prefix,
+            [{name: 'normalize', value: true}, {name: 'buffer', value: null}]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'ConvolverNode', {
+          channelCount:
+              {value: 2, isFixed: true, errorType: 'NotSupportedError'},
+          channelCountMode: {
+            value: 'clamped-max',
+            isFixed: true,
+            errorType: 'NotSupportedError'
+          },
+        });
+        task.done();
+      });
+
+      audit.define('nullable buffer', (task, should) => {
+        let node;
+        let options = {buffer: null};
+
+        should(
+            () => {
+              node = new ConvolverNode(context, options);
+            },
+            'node1 = new ConvolverNode(c, ' + JSON.stringify(options))
+            .notThrow();
+
+        should(node.buffer, 'node1.buffer').beEqualTo(null);
+
+        task.done();
+      });
+
+      audit.define('construct with options', (task, should) => {
+        let buf = context.createBuffer(1, 1, context.sampleRate);
+        let options = {buffer: buf, disableNormalization: false};
+
+        let message =
+            'node = new ConvolverNode(c, ' + JSON.stringify(options) + ')';
+
+        let node;
+        should(() => {
+          node = new ConvolverNode(context, options);
+        }, message).notThrow();
+
+        should(node instanceof ConvolverNode, 'node1 instanceOf ConvolverNode')
+            .beEqualTo(true);
+        should(node.buffer === options.buffer, 'node1.buffer === <buf>')
+            .beEqualTo(true);
+        should(node.normalize, 'node1.normalize')
+            .beEqualTo(!options.disableNormalization);
+
+        options.buffer = null;
+        options.disableNormalization = true;
+
+        message =
+            'node2 = new ConvolverNode(, ' + JSON.stringify(options) + ')';
+
+        should(() => {
+          node = new ConvolverNode(context, options);
+        }, message).notThrow();
+        should(node.buffer, 'node2.buffer').beEqualTo(null);
+        should(node.normalize, 'node2.normalize')
+            .beEqualTo(!options.disableNormalization);
+
+        options.disableNormalization = false;
+        message = 'node3 = new ConvolverNode(context, ' +
+            JSON.stringify(options) + ')';
+
+        should(() => {
+          node = new ConvolverNode(context, options);
+        }, message).notThrow();
+        should(node.buffer, 'node3.buffer').beEqualTo(null);
+        should(node.normalize, 'node3.normalize')
+            .beEqualTo(!options.disableNormalization);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-delaynode-interface/ctor-delay.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: Delay
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'DelayNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'DelayNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(
+            should, node, prefix, [{name: 'delayTime', value: 0}]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'DelayNode');
+        task.done();
+      });
+
+      audit.define('constructor options', (task, should) => {
+        let node;
+        let options = {
+          delayTime: 0.5,
+          maxDelayTime: 1.5,
+        };
+
+        should(
+            () => {
+              node = new DelayNode(context, options);
+            },
+            'node1 = new DelayNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        should(node.delayTime.value, 'node1.delayTime.value')
+            .beEqualTo(options.delayTime);
+        should(node.delayTime.maxValue, 'node1.delayTime.maxValue')
+            .beEqualTo(options.maxDelayTime);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-dynamicscompressornode-interface/ctor-dynamicscompressor.html
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: DynamicsCompressor
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'DynamicsCompressorNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node =
+            testDefaultConstructor(should, 'DynamicsCompressorNode', context, {
+              prefix: prefix,
+              numberOfInputs: 1,
+              numberOfOutputs: 1,
+              channelCount: 2,
+              channelCountMode: 'clamped-max',
+              channelInterpretation: 'speakers'
+            });
+
+        testDefaultAttributes(should, node, prefix, [
+          {name: 'threshold', value: -24}, {name: 'knee', value: 30},
+          {name: 'ratio', value: 12}, {name: 'reduction', value: 0},
+          {name: 'attack', value: Math.fround(0.003)},
+          {name: 'release', value: 0.25}
+        ]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        // Can't use testAudioNodeOptions because the constraints for this node
+        // are not supported there.
+
+        // Array of test options to be run.  Each entry is a dictionary where
+        // |testAttribute| is the name of the attribute to be tested,
+        // |testValue| is the value to be used, and |expectedErrorType| is the
+        // error type if the test is expected to throw an error.
+        // |expectedErrorType| should be set only if the test does throw.
+        let testOptions = [
+          // Test channel count
+          {
+            testAttribute: 'channelCount',
+            testValue: 1,
+          },
+          {
+            testAttribute: 'channelCount',
+            testValue: 2,
+          },
+          {
+            testAttribute: 'channelCount',
+            testValue: 0,
+            expectedErrorType: 'NotSupportedError'
+          },
+          {
+            testAttribute: 'channelCount',
+            testValue: 3,
+            expectedErrorType: 'NotSupportedError'
+          },
+          {
+            testAttribute: 'channelCount',
+            testValue: 99,
+            expectedErrorType: 'NotSupportedError'
+          },
+          // Test channel count mode
+          {
+            testAttribute: 'channelCountMode',
+            testValue: 'clamped-max',
+          },
+          {
+            testAttribute: 'channelCountMode',
+            testValue: 'explicit',
+          },
+          {
+            testAttribute: 'channelCountMode',
+            testValue: 'max',
+            expectedErrorType: 'NotSupportedError'
+          },
+          {
+            testAttribute: 'channelCountMode',
+            testValue: 'foobar',
+            expectedErrorType: 'TypeError'
+          },
+          // Test channel interpretation
+          {
+            testAttribute: 'channelInterpretation',
+            testValue: 'speakers',
+          },
+          {
+            testAttribute: 'channelInterpretation',
+            testValue: 'discrete',
+          },
+          {
+            testAttribute: 'channelInterpretation',
+            testValue: 'foobar',
+            expectedErrorType: 'TypeError'
+          }
+        ];
+
+        testOptions.forEach((option) => {
+          let nodeOptions = {};
+          nodeOptions[option.testAttribute] = option.testValue;
+
+          testNode(should, context, {
+            nodeOptions: nodeOptions,
+            testAttribute: option.testAttribute,
+            expectedValue: option.testValue,
+            expectedErrorType: option.expectedErrorType
+          });
+        });
+
+        task.done();
+      });
+
+      audit.define('constructor with options', (task, should) => {
+        let node;
+        let options =
+            {threshold: -33, knee: 15, ratio: 7, attack: 0.625, release: 0.125};
+
+        should(
+            () => {
+              node = new DynamicsCompressorNode(context, options);
+            },
+            'node1 = new DynamicsCompressorNode(c, ' + JSON.stringify(options) +
+                ')')
+            .notThrow();
+        should(
+            node instanceof DynamicsCompressorNode,
+            'node1 instanceof DynamicsCompressorNode')
+            .beEqualTo(true);
+
+        should(node.threshold.value, 'node1.threshold.value')
+            .beEqualTo(options.threshold);
+        should(node.knee.value, 'node1.knee.value').beEqualTo(options.knee);
+        should(node.ratio.value, 'node1.ratio.value').beEqualTo(options.ratio);
+        should(node.attack.value, 'node1.attack.value')
+            .beEqualTo(options.attack);
+        should(node.release.value, 'node1.release.value')
+            .beEqualTo(options.release);
+
+        should(node.channelCount, 'node1.channelCount').beEqualTo(2);
+        should(node.channelCountMode, 'node1.channelCountMode')
+            .beEqualTo('clamped-max');
+        should(node.channelInterpretation, 'node1.channelInterpretation')
+            .beEqualTo('speakers');
+
+        task.done();
+      });
+
+      audit.run();
+
+      // Test possible options for DynamicsCompressor constructor.
+      function testNode(should, context, options) {
+        // Node to be tested
+        let node;
+
+        let createNodeFunction = () => {
+          return () => node =
+                     new DynamicsCompressorNode(context, options.nodeOptions);
+        };
+
+        let message = 'new DynamicsCompressorNode(c, ' +
+            JSON.stringify(options.nodeOptions) + ')';
+
+        if (options.expectedErrorType) {
+          should(createNodeFunction(), message)
+              .throw(options.expectedErrorType);
+        } else {
+          should(createNodeFunction(), message).notThrow();
+          should(node[options.testAttribute], 'node.' + options.testAttribute)
+              .beEqualTo(options.expectedValue);
+        }
+      }
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-gainnode-interface/ctor-gain.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: Gain
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'GainNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'GainNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(should, node, prefix, [{name: 'gain', value: 1}]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'GainNode');
+        task.done();
+      });
+
+      audit.define('constructor with options', (task, should) => {
+        let node;
+        let options = {
+          gain: -2,
+        };
+
+        should(
+            () => {
+              node = new GainNode(context, options);
+            },
+            'node1 = new GainNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node instanceof GainNode, 'node1 instanceof GainNode')
+            .beEqualTo(true);
+
+        should(node.gain.value, 'node1.gain.value').beEqualTo(options.gain);
+
+        should(node.channelCount, 'node1.channelCount').beEqualTo(2);
+        should(node.channelCountMode, 'node1.channelCountMode')
+            .beEqualTo('max');
+        should(node.channelInterpretation, 'node1.channelInterpretation')
+            .beEqualTo('speakers');
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-iirfilternode-interface/ctor-iirfilter.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: IIRFilter
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'IIRFilterNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'IIRFilterNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'max',
+          channelInterpretation: 'speakers',
+          constructorOptions: {feedforward: [1], feedback: [1, -.9]}
+        });
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(
+            should, context, 'IIRFilterNode',
+            {additionalOptions: {feedforward: [1, 1], feedback: [1, .5]}});
+        task.done();
+      });
+
+      audit.define('constructor options', (task, should) => {
+        let node;
+
+        let options = {feedback: [1, .5]};
+        should(
+            () => {
+              node = new IIRFilterNode(context, options);
+            },
+            'node = new IIRFilterNode(, ' + JSON.stringify(options) + ')')
+            .throw('TypeError');
+
+        options = {feedforward: [1, 0.5]};
+        should(
+            () => {
+              node = new IIRFilterNode(context, options);
+            },
+            'node = new IIRFilterNode(c, ' + JSON.stringify(options) + ')')
+            .throw('TypeError');
+
+        task.done();
+      });
+
+      // Test functionality of constructor.  This is needed because we have no
+      // way of determining if the filter coefficients were were actually set
+      // appropriately.
+
+      // TODO(rtoy): This functionality test should be moved out to a separate
+      // file.
+      audit.define('functionality', (task, should) => {
+        let options = {feedback: [1, .5], feedforward: [1, 1]};
+
+        // Create two-channel offline context; sample rate and length are fairly
+        // arbitrary.  Channel 0 contains the test output and channel 1 contains
+        // the expected output.
+        let sampleRate = 48000;
+        let renderLength = 0.125;
+        let testContext =
+            new OfflineAudioContext(2, renderLength * sampleRate, sampleRate);
+
+        // The test node uses the constructor.  The reference node creates the
+        // same filter but uses the old factory method.
+        let testNode = new IIRFilterNode(testContext, options);
+        let refNode = testContext.createIIRFilter(
+            Float32Array.from(options.feedforward),
+            Float32Array.from(options.feedback));
+
+        let source = testContext.createOscillator();
+        source.connect(testNode);
+        source.connect(refNode);
+
+        let merger = testContext.createChannelMerger(
+            testContext.destination.channelCount);
+
+        testNode.connect(merger, 0, 0);
+        refNode.connect(merger, 0, 1);
+
+        merger.connect(testContext.destination);
+
+        source.start();
+        testContext.startRendering()
+            .then(function(resultBuffer) {
+              let actual = resultBuffer.getChannelData(0);
+              let expected = resultBuffer.getChannelData(1);
+
+              // The output from the two channels should be exactly equal
+              // because exactly the same IIR filter should have been created.
+              should(actual, 'Output of filter using new IIRFilter(...)')
+                  .beEqualToArray(expected);
+            })
+            .then(() => task.done());
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-offlineaudiocontext-interface/ctor-offlineaudiocontext.html
@@ -0,0 +1,203 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Constructor: OfflineAudioContext</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      // Just a simple test of the 3-arg constructor; This should be
+      // well-covered by other layout tests that use the 3-arg constructor.
+      audit.define(
+          {label: 'basic', description: 'Old-style constructor'},
+          (task, should) => {
+            let context;
+
+            // First and only arg should be a dictionary.
+            should(() => {
+              new OfflineAudioContext(3);
+            }, 'new OfflineAudioContext(3)').throw('TypeError');
+
+            // Constructor needs 1 or 3 args, so 2 should throw.
+            should(() => {
+              new OfflineAudioContext(3, 42);
+            }, 'new OfflineAudioContext(3, 42)').throw('TypeError');
+
+            // Valid constructor
+            should(() => {
+              context = new OfflineAudioContext(3, 42, 12345);
+            }, 'context = new OfflineAudioContext(3, 42, 12345)').notThrow();
+
+            // Verify that the context was constructed correctly.
+            should(context.length, 'context.length').beEqualTo(42);
+            should(context.sampleRate, 'context.sampleRate').beEqualTo(12345);
+            should(
+                context.destination.channelCount,
+                'context.destination.channelCount')
+                .beEqualTo(3);
+            should(
+                context.destination.channelCountMode,
+                'context.destination.channelCountMode')
+                .beEqualTo('explicit');
+            should(
+                context.destination.channelInterpretation,
+                'context.destination.channelInterpretation')
+                .beEqualTo('speakers');
+            task.done();
+          });
+
+      // Test constructor throws an error if the required members of the
+      // dictionary are not given.
+      audit.define(
+          {label: 'options-1', description: 'Required options'},
+          (task, should) => {
+            let context2;
+
+            // No args should throw
+            should(() => {
+              new OfflineAudioContext();
+            }, 'new OfflineAudioContext()').throw('TypeError');
+
+            // Empty OfflineAudioContextOptions should throw
+            should(() => {
+              new OfflineAudioContext({});
+            }, 'new OfflineAudioContext({})').throw('TypeError');
+
+            let options = {length: 42};
+            // sampleRate is required.
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('TypeError');
+
+            options = {sampleRate: 12345};
+            // length is required.
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('TypeError');
+
+            // Valid constructor.  Verify that the resulting context has the
+            // correct values.
+            options = {length: 42, sampleRate: 12345};
+            should(
+                () => {
+                  context2 = new OfflineAudioContext(options);
+                },
+                'c2 = new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .notThrow();
+            should(
+                context2.destination.channelCount,
+                'c2.destination.channelCount')
+                .beEqualTo(1);
+            should(context2.length, 'c2.length').beEqualTo(options.length);
+            should(context2.sampleRate, 'c2.sampleRate')
+                .beEqualTo(options.sampleRate);
+            should(
+                context2.destination.channelCountMode,
+                'c2.destination.channelCountMode')
+                .beEqualTo('explicit');
+            should(
+                context2.destination.channelInterpretation,
+                'c2.destination.channelInterpretation')
+                .beEqualTo('speakers');
+
+            task.done();
+          });
+
+      // Constructor should throw errors for invalid values specified by
+      // OfflineAudioContextOptions.
+      audit.define(
+          {label: 'options-2', description: 'Invalid options'},
+          (task, should) => {
+            let options = {length: 42, sampleRate: 8000, numberOfChannels: 33};
+
+            // channelCount too large.
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('NotSupportedError');
+
+            // length cannot be 0
+            options = {length: 0, sampleRate: 8000};
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('NotSupportedError');
+
+            // sampleRate outside valid range
+            options = {length: 1, sampleRate: 1};
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('NotSupportedError');
+
+            task.done();
+          });
+
+      audit.define(
+          {label: 'options-3', description: 'Valid options'},
+          (task, should) => {
+            let context;
+            let options = {
+              length: 1,
+              sampleRate: 8000,
+            };
+
+            // Verify context with valid constructor has the correct values.
+            should(
+                () => {
+                  context = new OfflineAudioContext(options);
+                },
+                'c = new OfflineAudioContext' + JSON.stringify(options) + ')')
+                .notThrow();
+            should(context.length, 'c.length').beEqualTo(options.length);
+            should(context.sampleRate, 'c.sampleRate')
+                .beEqualTo(options.sampleRate);
+            should(
+                context.destination.channelCount, 'c.destination.channelCount')
+                .beEqualTo(1);
+            should(
+                context.destination.channelCountMode,
+                'c.destination.channelCountMode')
+                .beEqualTo('explicit');
+            should(
+                context.destination.channelInterpretation,
+                'c.destination.channelCountMode')
+                .beEqualTo('speakers');
+
+            options.numberOfChannels = 7;
+            should(
+                () => {
+                  context = new OfflineAudioContext(options);
+                },
+                'c = new OfflineAudioContext' + JSON.stringify(options) + ')')
+                .notThrow();
+            should(
+                context.destination.channelCount, 'c.destination.channelCount')
+                .beEqualTo(options.numberOfChannels);
+
+            task.done();
+          });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-oscillatornode-interface/ctor-oscillator.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: Oscillator
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'OscillatorNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'OscillatorNode', context, {
+          prefix: prefix,
+          numberOfInputs: 0,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(
+            should, node, prefix,
+            [{name: 'type', value: 'sine'}, {name: 'frequency', value: 440}]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'OscillatorNode');
+        task.done();
+      });
+
+      audit.define('constructor options', (task, should) => {
+        let node;
+        let options = {type: 'sawtooth', detune: 7, frequency: 918};
+
+        should(
+            () => {
+              node = new OscillatorNode(context, options);
+            },
+            'node1 = new OscillatorNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+
+        should(node.type, 'node1.type').beEqualTo(options.type);
+        should(node.detune.value, 'node1.detune.value')
+            .beEqualTo(options.detune);
+        should(node.frequency.value, 'node1.frequency.value')
+            .beEqualTo(options.frequency);
+
+        should(node.channelCount, 'node1.channelCount').beEqualTo(2);
+        should(node.channelCountMode, 'node1.channelCountMode')
+            .beEqualTo('max');
+        should(node.channelInterpretation, 'node1.channelInterpretation')
+            .beEqualTo('speakers');
+
+        // Test that type and periodicWave options work as described.
+        options = {
+          type: 'sine',
+          periodicWave: new PeriodicWave(context, {real: [1, 1]})
+        };
+        should(() => {
+          node = new OscillatorNode(context, options);
+        }, 'new OscillatorNode(c, ' + JSON.stringify(options) + ')').notThrow();
+
+        options = {type: 'custom'};
+        should(
+            () => {
+              node = new OscillatorNode(context, options);
+            },
+            'new OscillatorNode(c, ' + JSON.stringify(options) + ')')
+            .throw('InvalidStateError');
+
+        options = {
+          type: 'custom',
+          periodicWave: new PeriodicWave(context, {real: [1, 1]})
+        };
+        should(() => {
+          node = new OscillatorNode(context, options);
+        }, 'new OscillatorNode(, ' + JSON.stringify(options) + ')').notThrow();
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html
@@ -0,0 +1,274 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: Panner
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'PannerNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'PannerNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'clamped-max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(should, node, prefix, [
+          {name: 'panningModel', value: 'equalpower'},
+          {name: 'positionX', value: 0}, {name: 'positionY', value: 0},
+          {name: 'positionZ', value: 0}, {name: 'orientationX', value: 1},
+          {name: 'orientationY', value: 0}, {name: 'orientationZ', value: 0},
+          {name: 'distanceModel', value: 'inverse'},
+          {name: 'refDistance', value: 1}, {name: 'maxDistance', value: 10000},
+          {name: 'rolloffFactor', value: 1},
+          {name: 'coneInnerAngle', value: 360},
+          {name: 'coneOuterAngle', value: 360},
+          {name: 'coneOuterGain', value: 0}
+        ]);
+
+        // Test the listener too, while we're at it.
+        let listenerAttributes = [
+          {name: 'positionX', value: 0},
+          {name: 'positionY', value: 0},
+          {name: 'positionZ', value: 0},
+          {name: 'forwardX', value: 0},
+          {name: 'forwardY', value: 0},
+          {name: 'forwardZ', value: -1},
+          {name: 'upX', value: 0},
+          {name: 'upY', value: 1},
+          {name: 'upZ', value: 0},
+        ];
+
+        listenerAttributes.forEach((item) => {
+          should(
+              context.listener[item.name].value,
+              'context.listener.' + item.name + '.value')
+              .beEqualTo(item.value);
+        });
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        // Can't use testAudioNodeOptions because the constraints for this node
+        // are not supported there.
+        let node;
+        let success = true;
+
+        // Test that we can set the channel count to 1 or 2.
+        let options = {channelCount: 1};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'node1 = new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node.channelCount, 'node1.channelCount')
+            .beEqualTo(options.channelCount);
+
+        options = {channelCount: 2};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'node2 = new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node.channelCount, 'node2.channelCount')
+            .beEqualTo(options.channelCount);
+
+        // Test that other channel counts throw an error
+        options = {channelCount: 0};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('NotSupportedError');
+
+        options = {channelCount: 3};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('NotSupportedError');
+
+        options = {channelCount: 99};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('NotSupportedError');
+
+        // Test channelCountMode.  A mode of "max" is illegal, but others are
+        // ok.
+        options = {channelCountMode: 'clamped-max'};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'node3 = new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node.channelCountMode, 'node3.channelCountMode')
+            .beEqualTo(options.channelCountMode);
+
+        options = {channelCountMode: 'explicit'};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'node4 = new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node.channelCountMode, 'node4.channelCountMode')
+            .beEqualTo(options.channelCountMode);
+
+        options = {channelCountMode: 'max'};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('NotSupportedError');
+
+        options = {channelCountMode: 'foobar'};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'new PannerNode(c, " + JSON.stringify(options) + ")')
+            .throw('TypeError');
+
+        // Test channelInterpretation.
+        options = {channelInterpretation: 'speakers'};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'node5 = new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node.channelInterpretation, 'node5.channelInterpretation')
+            .beEqualTo(options.channelInterpretation);
+
+        options = {channelInterpretation: 'discrete'};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'node6 = new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node.channelInterpretation, 'node6.channelInterpretation')
+            .beEqualTo(options.channelInterpretation);
+
+        options = {channelInterpretation: 'foobar'};
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .throw('TypeError');
+
+        task.done();
+      });
+
+      audit.define('constructor with options', (task, should) => {
+        let node;
+        let success = true;
+        let options = {
+          panningModel: 'HRTF',
+          // We use full double float values here to verify also that the actual
+          // AudioParam value is properly rounded to a float.  The actual value
+          // is immaterial as long as x != Math.fround(x).
+          positionX: Math.SQRT2,
+          positionY: 2 * Math.SQRT2,
+          positionZ: 3 * Math.SQRT2,
+          orientationX: -Math.SQRT2,
+          orientationY: -2 * Math.SQRT2,
+          orientationZ: -3 * Math.SQRT2,
+          distanceModel: 'linear',
+          // We use full double float values here to verify also that the actual
+          // attribute is a double float.  The actual value is immaterial as
+          // long as x != Math.fround(x).
+          refDistance: Math.PI,
+          maxDistance: 2 * Math.PI,
+          rolloffFactor: 3 * Math.PI,
+          coneInnerAngle: 4 * Math.PI,
+          coneOuterAngle: 5 * Math.PI,
+          coneOuterGain: 6 * Math.PI
+        };
+
+        should(
+            () => {
+              node = new PannerNode(context, options);
+            },
+            'node = new PannerNode(c, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(node instanceof PannerNode, 'node instanceof PannerNode')
+            .beEqualTo(true);
+
+        should(node.panningModel, 'node.panningModel')
+            .beEqualTo(options.panningModel);
+        should(node.positionX.value, 'node.positionX.value')
+            .beEqualTo(Math.fround(options.positionX));
+        should(node.positionY.value, 'node.positionY.value')
+            .beEqualTo(Math.fround(options.positionY));
+        should(node.positionZ.value, 'node.positionZ.value')
+            .beEqualTo(Math.fround(options.positionZ));
+        should(node.orientationX.value, 'node.orientationX.value')
+            .beEqualTo(Math.fround(options.orientationX));
+        should(node.orientationY.value, 'node.orientationY.value')
+            .beEqualTo(Math.fround(options.orientationY));
+        should(node.orientationZ.value, 'node.orientationZ.value')
+            .beEqualTo(Math.fround(options.orientationZ));
+        should(node.distanceModel, 'node.distanceModel')
+            .beEqualTo(options.distanceModel);
+        should(node.refDistance, 'node.refDistance')
+            .beEqualTo(options.refDistance);
+        should(node.maxDistance, 'node.maxDistance')
+            .beEqualTo(options.maxDistance);
+        should(node.rolloffFactor, 'node.rolloffFactor')
+            .beEqualTo(options.rolloffFactor);
+        should(node.coneInnerAngle, 'node.coneInnerAngle')
+            .beEqualTo(options.coneInnerAngle);
+        should(node.coneOuterAngle, 'node.coneOuterAngle')
+            .beEqualTo(options.coneOuterAngle);
+        should(node.coneOuterGain, 'node.coneOuterGain')
+            .beEqualTo(options.coneOuterGain);
+
+        should(node.channelCount, 'node.channelCount').beEqualTo(2);
+        should(node.channelCountMode, 'node.channelCountMode')
+            .beEqualTo('clamped-max');
+        should(node.channelInterpretation, 'node.channelInterpretation')
+            .beEqualTo('speakers');
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-stereopanner-interface/ctor-stereopanner.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: StereoPanner
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('invalid constructor', (task, should) => {
+        testInvalidConstructor(should, 'StereoPannerNode', context);
+        task.done();
+      });
+
+      audit.define('default constructor', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'StereoPannerNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'clamped-max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(should, node, prefix, [{name: 'pan', value: 0}]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        // Can't use testAudioNodeOptions because the constraints for this node
+        // are not supported there.
+        let node;
+
+        // An array of tests.
+        [{
+          // Test that we can set the channel count to 1 or 2 and that other
+          // channel counts throw an error.
+          attribute: 'channelCount',
+          tests: [
+            {value: 1}, {value: 2}, {value: 0, error: 'NotSupportedError'},
+            {value: 3, error: 'NotSupportedError'},
+            {value: 99, error: 'NotSupportedError'}
+          ]
+        },
+         {
+           // Test channelCountMode.  A mode of "max" is illegal, but others are
+           // ok.  But also throw an error of unknown values.
+           attribute: 'channelCountMode',
+           tests: [
+             {value: 'clamped-max'}, {value: 'explicit'},
+             {value: 'max', error: 'NotSupportedError'},
+             {value: 'foobar', error: 'TypeError'}
+           ]
+         },
+         {
+           // Test channelInterpretation can be set for valid values and an
+           // error is thrown for others.
+           attribute: 'channelInterpretation',
+           tests: [
+             {value: 'speakers'}, {value: 'discrete'},
+             {value: 'foobar', error: 'TypeError'}
+           ]
+         }].forEach(entry => {
+          entry.tests.forEach(testItem => {
+            let options = {};
+            options[entry.attribute] = testItem.value;
+            let method = testItem.error ? 'throw' : 'notThrow';
+
+            should(
+                () => {
+                  node = new StereoPannerNode(context, options);
+                },
+                `new StereoPannerNode(c, ${JSON.stringify(options)})`)[method](
+                testItem.error);
+            if (!testItem.error)
+              should(node[entry.attribute], `node.${entry.attribute}`)
+                  .beEqualTo(options[entry.attribute]);
+          });
+        });
+
+        task.done();
+      });
+
+      audit.define('constructor with options', (task, should) => {
+        let node;
+        let options = {
+          pan: 0.75,
+        };
+
+        should(
+            () => {
+              node = new StereoPannerNode(context, options);
+            },
+            'node1 = new StereoPannerNode(, ' + JSON.stringify(options) + ')')
+            .notThrow();
+        should(
+            node instanceof StereoPannerNode,
+            'node1 instanceof StereoPannerNode')
+            .beEqualTo(true);
+
+        should(node.pan.value, 'node1.pan.value').beEqualTo(options.pan);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-waveshapernode-interface/ctor-waveshaper.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>
+      Test Constructor: WaveShaper
+    </title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+    <script src="/webaudio/resources/audionodeoptions.js"></script>
+  </head>
+  <body>
+    <script id="layout-test-code">
+      let context;
+
+      let audit = Audit.createTaskRunner();
+
+      audit.define('initialize', (task, should) => {
+        context = initializeContext(should);
+        task.done();
+      });
+
+      audit.define('incorrect construction', (task, should) => {
+        testInvalidConstructor(should, 'WaveShaperNode', context);
+        task.done();
+      });
+
+      audit.define('valid default construction', (task, should) => {
+        let prefix = 'node0';
+        let node = testDefaultConstructor(should, 'WaveShaperNode', context, {
+          prefix: prefix,
+          numberOfInputs: 1,
+          numberOfOutputs: 1,
+          channelCount: 2,
+          channelCountMode: 'max',
+          channelInterpretation: 'speakers'
+        });
+
+        testDefaultAttributes(should, node, prefix, [
+          {name: 'curve', value: null}, {name: 'oversample', value: 'none'}
+        ]);
+
+        task.done();
+      });
+
+      audit.define('test AudioNodeOptions', (task, should) => {
+        testAudioNodeOptions(should, context, 'WaveShaperNode');
+        task.done();
+      });
+
+      audit.define('valid non-default', (task, should) => {
+        // Construct an WaveShaperNode with options
+        let options = {curve: Float32Array.from([1, 2, 3]), oversample: '4x'};
+        let node;
+
+        let message =
+            'node1 = new WaveShaperNode(, ' + JSON.stringify(options) + ')';
+        should(() => {
+          node = new WaveShaperNode(context, options);
+        }, message).notThrow();
+        should(node.curve, 'node1.curve').beEqualToArray(options.curve);
+        should(node.oversample, 'node1.oversample')
+            .beEqualTo(options.oversample);
+
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>