1 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
4 <script src=
"resources/compatibility.js"></script>
5 <script src=
"resources/audio-testing.js"></script>
6 <script src=
"../resources/js-test.js"></script>
7 <script src=
"resources/biquad-testing.js"></script>
12 <div id=
"description"></div>
13 <div id=
"console"></div>
15 description("Tests DOM exception messages");
25 function shouldThrowAndBeUnchanged(attr
, value
) {
26 shouldThrow(attr
+ " = " + value
);
27 shouldNotBe(attr
, value
);
31 if (window
.testRunner
) {
32 testRunner
.dumpAsText();
35 context
= new AudioContext();
36 otherContext
= new AudioContext();
38 // Test creation of various objects
40 // Invalid number of channels: NotSupportedError
41 shouldThrow("context.createBuffer(99, 1, context.sampleRate)");
42 shouldThrow("context.createBuffer(0, 1, context.sampleRate)");
43 // Invalid sample rate: NotSupportedError
44 shouldThrow("context.createBuffer(1, 1, 1)");
45 shouldThrow("context.createBuffer(1, 1, 1e6)");
46 // Check valid values from crbug.com/344375
47 shouldNotThrow("context.createBuffer(1, 1, 3000)");
48 shouldNotThrow("context.createBuffer(1, 1, 192000)");
49 // Invalid number of frames: NotSupportedError
50 shouldThrow("context.createBuffer(1, 0, context.sampleRate)");
51 // 2-arg createBuffer not allowed.
52 shouldThrow("context.createBuffer(new ArrayBuffer(100), true)");
53 // Invalid ArrayBuffer (unspecified error)
54 shouldThrow("context.decodeAudioData(null, function() {}, function () {})");
55 // Invalid sources (unspecified error)
56 shouldThrow("context.createMediaElementSource(null)");
57 shouldThrow("context.createMediaStreamSource(null)");
58 // Invalid buffer size: IndexSizeError
59 shouldThrow("context.createScriptProcessor(1, 1, 1)");
60 // Invalid number of inputs and outputs: IndexSizeError
61 shouldThrow("context.createScriptProcessor(4096, 100, 1)");
62 shouldThrow("context.createScriptProcessor(4096, 1, 100)");
63 shouldNotThrow("context.createScriptProcessor()");
64 shouldNotThrow("context.createScriptProcessor(0)");
66 // Invalid number of channels: IndexSizeError
67 shouldThrow("context.createChannelSplitter(0)");
68 shouldThrow("context.createChannelSplitter(99)");
69 shouldThrow("context.createChannelMerger(0)");
70 shouldThrow("context.createChannelMerger(99)");
71 // Invalid real/imag arrays: IndexSizeError
72 shouldThrow("context.createPeriodicWave(null, null)");
73 shouldThrow("context.createPeriodicWave(new Float32Array(10), null)");
74 // Verify that we can use large arrays with no limit. Roughly.
75 shouldNotThrow("context.createPeriodicWave(new Float32Array(4100), new Float32Array(4100))");
76 shouldNotThrow("context.createPeriodicWave(new Float32Array(8192), new Float32Array(8192))");
77 shouldNotThrow("context.createPeriodicWave(new Float32Array(10000), new Float32Array(10000))");
78 // Real and imaginary arrays must have the same size: IndexSizeError
79 shouldThrow("context.createPeriodicWave(new Float32Array(10), new Float32Array(7))");
83 node
= context
.createAnalyser();
84 // Invalid fftSize: IndexSizeError
85 shouldThrowAndBeUnchanged("node.fftSize", "42");
86 shouldThrowAndBeUnchanged("node.fftSize", "16");
87 shouldNotThrow("node.fftSize = 32768");
88 shouldThrowAndBeUnchanged("node.fftSize", "65536");
90 shouldThrowAndBeUnchanged("node.minDecibels", "-10");
91 shouldThrowAndBeUnchanged("node.maxDecibels", "-150");
92 shouldThrowAndBeUnchanged("node.minDecibels", "-30");
93 shouldThrowAndBeUnchanged("node.maxDecibels", "-100");
95 shouldThrowAndBeUnchanged("node.smoothingTimeConstant", "-0.1");
96 shouldThrowAndBeUnchanged("node.smoothingTimeConstant", "1.5");
99 node
= context
.createBuffer(1,1, context
.sampleRate
);
100 // Invalid channel index: IndexSizeError
101 shouldThrow("node.getChannelData(2)");
103 // AudioNode connections
104 node
= context
.createGain();
105 node2
= context
.createGain();
106 // Invalid destination node (unspecified error)
107 shouldThrow("node.connect(null, 0, 0)");
108 // Invalid input or output index: IndexSizeError
109 shouldThrow("node.connect(context.destination, 100, 0)");
110 shouldThrow("node.connect(context.destination, 0, 100)");
111 shouldThrow("node.connect(node2.gain, 100)");
112 shouldThrow("node.disconnect(99)");
113 // Can't connect to a different context (unspecified error)
114 shouldThrow("node.connect(otherContext.destination)");
116 // Invalid channel count: NotSupportedError
117 shouldThrowAndBeUnchanged("node.channelCount", "99");
118 // Invalid mode or interpretation (unspecified error)
119 currentMode
= node
.channelCountMode
;
120 currentInterpretation
= node
.channelInterpretation
;
121 shouldNotThrow("node.channelCountMode = 'fancy'");
122 if (node
.channelCountMode
== currentMode
)
123 testPassed("Invalid channelCountMode value did not change mode");
125 testFailed("node.channelCountMode incorrectly changed to invalid value " + node
.channelCountMode
);
126 shouldNotThrow("node.channelInterpretation = mode");
127 if (node
.channelInterpretation
== currentInterpretation
)
128 testPassed("Invalid channelInterpration value did not change mode");
130 testFailed("node.channelInterpretation incorrectly changed to invalid value " + node
.channelInterpreation
);
132 // Destination node channel count: should throw IndexSizeError on invalid
133 // channel count. shouldNotThrow() method cannot be used because the error
134 // message includes the number of channels, which can change depending on
135 // the actual attached hardware.
137 eval("context.destination.channelCount = 99");
139 if (e
.message
=== "Failed to set the 'channelCount' property on 'AudioNode': The channel count provided (99) is outside the range [1, " + context
.destination
.maxChannelCount
+ "]." && e
.name
=== "IndexSizeError")
140 testPassed("context.destination.channelCount = 99 threw IndexSizeError exception on invalid channel count.");
142 testFailed("context.destination.channelCount = 99 should throw IndexSizeError exception on invalid channel count.");
145 // Delay nodes are tested elsewhere, so don't duplicate that work here.
147 // OfflineAudioContext
148 // Max supported channels
149 shouldNotThrow("new OfflineAudioContext(32, 100, context.sampleRate)");
150 // Invalid number of channels (unspecified error)
151 shouldThrow("new OfflineAudioContext(99, 100, context.sampleRate)");
152 // Invalid sample rate. (unspecified error)
153 shouldThrow("new OfflineAudioContext(1, 100, 1)");
154 shouldThrow("new OfflineAudioContext(1, 100, 1e6)");
155 // Invalid frame length (crbug.com/351277)
156 shouldThrow("new OfflineAudioContext(1, -88200000000000, 44100)");
159 node
= context
.createWaveShaper();
160 currentOversample
= node
.oversample
;
161 shouldNotThrow("node.oversample = '9x'");
162 if (node
.oversample
== currentOversample
)
163 testPassed("Invalid oversample value did not change node.oversample");
165 testFailed("node.oversample incorrectly changed to invalid value " + node
.oversample
);
166 shouldThrow("node.curve = new Float32Array(1)");
167 shouldBeNull("node.curve");
168 shouldNotThrow("node.curve = new Float32Array(2)");
169 shouldNotThrow("node.curve = null");
171 // Start/stop for AudioBufferSourceNodes
172 buffer
= context
.createBuffer(1,1, context
.sampleRate
);
173 shouldNotThrow("source = context.createBufferSource()");
174 shouldNotThrow("source.buffer = buffer");
175 shouldThrow("source.buffer = context.createBuffer(1, 10, context.sampleRate)");
176 shouldThrow("source.start(-1)");
177 shouldThrow("source.start(Infinity)");
178 shouldThrow("source.start(-Infinity)");
179 shouldThrow("source.start(NaN)");
180 shouldThrow("source.start(1, Infinity)");
181 shouldThrow("source.start(1, -Infinity)");
182 shouldThrow("source.start(1, NaN)");
183 shouldThrow("source.start(1, -1)");
184 shouldThrow("source.start(1, -Number.MIN_VALUE)");
185 shouldThrow("source.start(1, 1, Infinity)");
186 shouldThrow("source.start(1, 1, -Infinity)");
187 shouldThrow("source.start(1, 1, NaN)");
188 shouldThrow("source.start(1, 1, -1)");
189 shouldThrow("source.start(1, 1, -Number.MIN_VALUE)");
190 shouldNotThrow("source.start()");
191 shouldThrow("source.stop(-Number.MIN_VALUE)");
192 shouldThrow("source.stop(Infinity)");
193 shouldThrow("source.stop(-Infinity)");
194 shouldThrow("source.stop(NaN)");
195 shouldNotThrow("source.stop()");
197 // Verify that start(0, 0) doesn't signal.
198 shouldNotThrow("source = context.createBufferSource()");
199 shouldNotThrow("source.buffer = buffer");
200 shouldNotThrow("source.start(0, 0)");
202 // Verify that start(0, -0.0) doesn't signal.
203 shouldNotThrow("source = context.createBufferSource()");
204 shouldNotThrow("source.buffer = buffer");
205 shouldNotThrow("source.start(0, -1/Infinity)");
207 // It's not clear from the spec, but I think it's valid to call start(). The spec is silent on
208 // what happens if we call stop() afterwards, so don't call it.
209 shouldNotThrow("source = context.createBufferSource()");
210 shouldNotThrow("source.start()");
212 buffer
= context
.createBuffer(1,1, context
.sampleRate
);
213 shouldNotThrow("source = context.createBufferSource()");
214 shouldNotThrow("source.buffer = buffer");
215 shouldThrow("source.stop()");
217 buffer
= context
.createBuffer(1,1, context
.sampleRate
);
218 shouldNotThrow("source = context.createBufferSource()");
219 shouldNotThrow("source.buffer = buffer");
220 shouldNotThrow("source.start()");
221 shouldThrow("source.start()");
223 buffer
= context
.createBuffer(1,1, context
.sampleRate
);
224 shouldNotThrow("source = context.createBufferSource()");
225 shouldNotThrow("source.buffer = buffer");
226 shouldNotThrow("source.start()");
227 shouldNotThrow("source.stop()");
230 // Start/stop for OscillatorNodes
231 shouldNotThrow("source = context.createOscillator()");
232 shouldThrow("source.start(-Number.MIN_VALUE)");
233 shouldThrow("source.start(Infinity)");
234 shouldThrow("source.start(-Infinity)");
235 shouldThrow("source.start(NaN)");
236 shouldNotThrow("source.start()");
237 shouldThrow("source.stop(-Number.MIN_VALUE)");
238 shouldThrow("source.stop(Infinity)");
239 shouldThrow("source.stop(-Infinity)");
240 shouldThrow("source.stop(NaN)");
241 shouldNotThrow("source.stop()");
243 shouldNotThrow("osc = context.createOscillator()");
244 shouldThrow("osc.stop()");
245 shouldNotThrow("osc1 = context.createOscillator()");
246 shouldNotThrow("osc1.start()");
247 shouldNotThrow("osc1.stop()");
249 // exponentialRampToValue should throw on non-positive target values.
250 node
= context
.createGain();
251 node
.connect(context
.destination
);
252 shouldThrow("node.gain.exponentialRampToValueAtTime(-1, 0.1)");
253 shouldThrow("node.gain.exponentialRampToValueAtTime(0, 0.1)");
254 // See crbug.com/459391.
255 // Math.pow(2, -149) = 1.401298464324817e-45 is the double-float value of the
256 // least positive single float number. We do it this way to make sure no round-off or conversion
257 // errors happen when reading 1.401298464324817e-45.
258 shouldNotThrow("node.gain.exponentialRampToValueAtTime(Math.pow(2, -149), 0.1)");
259 // Math.pow(2, -150) = 7.006492321624085d-46 is the largest double float value such that
260 // conversion to a float produces 0. Any larger value would produce a non-zero value when
261 // converted to a single float.
262 shouldThrow("node.gain.exponentialRampToValueAtTime(Math.pow(2, -150), 0.1)");
264 // Convolver buffer rate must match context rate. Create on offline context so we
265 // specify the context rate exactly, in case the test is run on platforms with different
267 shouldNotThrow("oc = new OfflineAudioContext(1, 44100, 44100)");
268 shouldNotThrow("conv = oc.createConvolver()");
269 shouldThrow("conv.buffer = oc.createBuffer(1, 100, 22050)");
270 // conv.buffer should be unchanged (null) because the above failed.
271 shouldBeNull("conv.buffer");
273 // PannerNode channel count and mode
274 panner
= context
.createPanner();
275 // Channel count can only be set to 1 or 2.
276 shouldNotThrow("panner.channelCount = 1");
277 shouldNotThrow("panner.channelCount = 2");
278 shouldThrowAndBeUnchanged("panner.channelCount", "0");
279 shouldThrowAndBeUnchanged("panner.channelCount", "3");
280 // It is illegal to set the mode to 'max'
281 shouldThrowAndBeUnchanged("panner.channelCountMode", "'max'");
282 shouldNotThrow("panner.channelCountMode = 'explicit'");
283 shouldNotThrow("panner.channelCountMode = 'clamped-max'");
284 shouldNotThrow("panner.channelCountMode = 'junk'");
286 // Test channel count and mode for a ScriptProcessor.
287 shouldNotThrow("script = context.createScriptProcessor(256, 3)");
288 // Make sure the channelCount and mode are set correctly.
289 shouldBeEqualToNumber("script.channelCount", 3);
290 shouldBeEqualToString("script.channelCountMode", "explicit");
291 // Cannot change the channelCount or mode to anything else
292 shouldNotThrow("script.channelCount = 3");
293 shouldThrowAndBeUnchanged("script.channelCount", "1");
295 shouldThrowAndBeUnchanged("script.channelCount", "7");
296 shouldNotThrow("script.channelCountMode = 'explicit'");
297 shouldThrowAndBeUnchanged("script.channelCountMode", "'max'");
298 shouldThrowAndBeUnchanged("script.channelCountMode", "'clamped-max'");
299 shouldNotThrow("script.channelCountMode = 'junk'");
301 // noteOn and noteOff don't exist anymore
302 shouldBeUndefined("osc.noteOn");
303 shouldBeUndefined("osc.noteOff");
304 shouldBeUndefined("source.noteOn");
305 shouldBeUndefined("source.noteOff");
309 successfullyParsed
= true;