1 window
.jsTestIsAsync
= true;
3 description('Test transfer of control semantics for ArrayBuffers.');
4 window
.testsComplete
= 0;
8 var arrayEffectiveSize
= arraySize
- arrayOffset
;
10 var basicBufferTypes
=
12 ["Int32", Int32Array
, 4],
13 ["Uint32", Uint32Array
, 4],
14 ["Int8", Int8Array
, 1],
15 ["Uint8", Uint8Array
, 1],
16 ["Uint8Clamped", Uint8ClampedArray
, 1],
17 ["Int16", Int16Array
, 2],
18 ["Uint16", Uint16Array
, 2],
19 ["Float32", Float32Array
, 4],
20 ["Float64", Float64Array
, 8]
25 ["Int32", Int32Array
, 4],
26 ["Uint32", Uint32Array
, 4],
27 ["Int8", Int8Array
, 1],
28 ["Uint8", Uint8Array
, 1],
29 ["Uint8Clamped", Uint8ClampedArray
, 1],
30 ["Int16", Int16Array
, 2],
31 ["Uint16", Uint16Array
, 2],
32 ["Float32", Float32Array
, 4],
33 ["Float64", Float64Array
, 8],
34 ["DataView", DataView
, 1]
37 function isTypedArray(view
)
39 for (var i
= 0; i
< basicBufferTypes
.length
; ++i
) {
40 var bufferType
= basicBufferTypes
[i
];
41 if (view
instanceof bufferType
[1]) {
48 function isDataView(view
)
50 return (view
instanceof DataView
);
53 function isArrayBuffer(buffer
)
55 return (buffer
instanceof ArrayBuffer
);
58 function isDataCloneError(e
)
60 return (e
.name
=== "DataCloneError");
63 function assertBufferClosed(testName
, buffer
)
65 if (buffer
=== null) {
68 if (!isArrayBuffer(buffer
)) {
69 testFailed(testName
+ ": not an array buffer (" + buffer
+ ")");
72 if (buffer
.byteLength
!== 0 || !(buffer
.byteLength
=== 0)) {
73 testFailed(testName
+ ": ArrayBuffer byteLength !== 0");
79 function assertViewClosed(testName
, view
)
81 if (isTypedArray(view
) || isDataView(view
)) {
82 if (view
.buffer
!== null && !assertBufferClosed(testName
, view
.buffer
))
84 if (view
.byteOffset
!== 0 || !(view
.byteOffset
=== 0)) {
85 testFailed(testName
+ ": view byteOffset !== 0");
88 if (view
.byteLength
!== 0 || !(view
.byteLength
=== 0)) {
89 testFailed(testName
+ ": view byteLength !== 0");
92 if (!isDataView(view
)) {
93 if (view
.length
!== 0 || !(view
.length
=== 0)) {
94 testFailed(testName
+ ": TypedArray length !== 0");
99 if (v
!== undefined) {
100 testFailed(testName
+ ": index get on a closed view did not return undefined.");
104 testFailed(testName
+ ": index get on a closed view threw an exception: " + xn
);
110 if (v
!== undefined) {
111 testFailed(testName
+ ": index set then get on a closed view did not return undefined.");
115 testFailed(testName
+ ": index set then get on a closed view threw an exception: " + xn
);
120 testFailed(testName
+ ": get on a closed view succeeded");
125 testFailed(testName
+ ": set on a closed view succeeded");
131 testFailed(testName
+ ": get on a closed view succeeded");
136 testFailed(testName
+ ": set on a closed view succeeded");
141 testFailed(testName
+ " not a view (" + view
+ ")");
147 function createBuffer(length
)
149 var buffer
= new ArrayBuffer(length
);
150 var view
= new Uint8Array(buffer
);
151 for (var i
= 0; i
< length
; ++i
) {
157 function checkBuffer(testName
, buffer
, length
)
159 if (!isArrayBuffer(buffer
)) {
160 testFailed(testName
+ ": buffer is not an ArrayBuffer");
163 if (buffer
.byteLength
!== length
) {
164 testFailed(testName
+ ": buffer is the wrong length");
167 var view
= new Uint8Array(buffer
);
168 for (var i
= 0; i
< length
; ++i
) {
169 if (view
[i
] !== i
+ 1) {
170 testFailed(testName
+ ": buffer contains the wrong data");
177 function createView(viewType
, bytesPerElement
)
179 if (viewType
=== DataView
) {
180 var view
= new Uint8Array(arraySize
);
181 for (var i
= arrayOffset
; i
< arraySize
; ++i
) {
182 view
[i
] = i
- arrayOffset
+ 1;
184 return new DataView(view
.buffer
, arrayOffset
, arrayEffectiveSize
);
186 var view
= new viewType(new ArrayBuffer(arraySize
), arrayOffset
, arrayEffectiveSize
/ bytesPerElement
);
187 for (var i
= 0; i
< arrayEffectiveSize
/ bytesPerElement
; ++i
) {
194 function createEveryView(buffer
)
196 return allBufferTypes
.map(function (bufferType
) {
197 return new bufferType
[1](buffer
, arrayOffset
, arrayEffectiveSize
/ bufferType
[2]);
201 function checkView(testName
, typedArrayType
, view
)
203 if (!(view
instanceof typedArrayType
)) {
204 testFailed(testName
+ ": " + view
+ " not an instance of " + typedArrayType
);
207 if (view
.buffer
.byteLength
!== arraySize
||
208 (!(view
instanceof DataView
) && view
.length
!== arrayEffectiveSize
/ view
.BYTES_PER_ELEMENT
)) {
209 testFailed(testName
+ ": view has the wrong length (" + view
.length
+ ")");
212 if (view
.byteOffset
!== arrayOffset
) {
213 testFailed(testName
+ ": view has wrong byte offset");
215 var max
= arrayEffectiveSize
;
216 if (!(view
instanceof DataView
)) {
217 max
= max
/ view
.BYTES_PER_ELEMENT
;
219 for (var i
= 0; i
< max
; ++i
) {
220 if (view
instanceof DataView
) {
221 if (view
.getInt8(i
) !== i
+ 1) {
222 testFailed(testName
+ ": view contains the wrong data");
226 if (view
[i
] !== i
+ 1) {
227 testFailed(testName
+ ": view contains the wrong data");
235 function checkEmptyArray(testName
, array
)
237 if (array
=== null || array
=== undefined) {
238 testFailed(testName
+ ": port list is null or undefined");
241 if (array
.length
!== 0) {
242 testFailed(testName
+ ": port list is not zero-length");
248 function wrapSend(testName
, message
, xfer
)
251 window
.postMessage(message
, '*', xfer
);
253 testFailed(testName
+ ": could not postMessage: " + e
);
260 function wrapFailSend(testName
, message
, xfer
)
263 window
.postMessage(message
, '*', xfer
);
265 if (!isDataCloneError(e
)) {
266 testFailed(testName
+ ": expected postMessage to throw DataCloneError but it didn't.");
271 testFailed(testName
+ ": expected postMessage to fail but it didn't.");
276 name
: "sanity check",
277 send: function (name
) { wrapSend(name
, [], []); },
278 test: function (name
, e
) { return true; }
280 name
: "raw ArrayBuffer",
281 send: function (name
) {
282 var buffer
= createBuffer(3);
283 wrapSend(name
, buffer
, [buffer
]);
284 assertBufferClosed(name
, buffer
);
285 wrapFailSend(name
, buffer
, [buffer
]);
286 wrapFailSend(name
, buffer
, []);
288 test: function (name
, e
) { return checkBuffer(name
, e
.data
, 3) && checkEmptyArray(name
, e
.ports
); }
290 name
: "sending buffers is sane even if cloning doesn't special-case",
291 send: function(name
) {
292 var view
= createView(Int32Array
, 4);
293 var buffer
= view
.buffer
;
294 wrapSend(name
, [view
, buffer
], [buffer
]);
295 assertBufferClosed(name
, buffer
);
296 assertViewClosed(name
, view
);
298 test: function (name
, e
) {
299 if (e
.data
[0].buffer
!== e
.data
[1]) {
300 testFailed("View and buffer were not linked.");
306 name
: "send every view",
307 send: function(name
) {
308 var buffer
= createBuffer(arraySize
);
309 var views
= createEveryView(buffer
);
310 wrapSend(name
, views
, [buffer
]);
311 assertBufferClosed(name
, buffer
);
312 wrapFailSend(name
, views
, [buffer
]);
313 wrapFailSend(name
, views
, []);
315 test: function (name
, e
) {
316 if (e
.data
.length
!== allBufferTypes
.length
) {
317 testFailed(name
+ ": not every view was sent.");
319 for (var v
= 0; v
< e
.data
.length
; ++v
) {
320 var view
= e
.data
[v
];
321 if (view
.buffer
!== e
.data
[0].buffer
) {
322 testFailed(name
+ ": not every view pointed to the correct buffer.");
329 name
: "transfer list multiple",
330 send: function(name
) {
331 var buffer0
= createBuffer(arraySize
);
332 wrapFailSend(name
, { buffer
: buffer0
}, [buffer0
, buffer0
]);
333 var buffer
= createBuffer(arraySize
);
334 wrapSend(name
, { buffer
: buffer
}, [buffer
]);
335 assertBufferClosed(name
, buffer
);
336 wrapFailSend(name
, [buffer
], [buffer
]);
337 wrapFailSend(name
, [], [buffer
]);
338 var buffer2
= createBuffer(arraySize
);
339 wrapFailSend(name
, [], [buffer2
, buffer
]);
340 checkBuffer(name
, buffer2
, arraySize
);
341 wrapFailSend(name
, [], [buffer
, buffer2
]);
342 checkBuffer(name
, buffer2
, arraySize
);
343 wrapFailSend(name
, [buffer2
], [buffer2
, buffer
]);
344 checkBuffer(name
, buffer2
, arraySize
);
346 test: function (name
, e
) {
347 return checkBuffer(name
, e
.data
.buffer
, arraySize
);
350 name
: "transfer neuters unmentioned",
351 send: function (name
) {
352 var buffer
= createBuffer(arraySize
);
353 wrapSend(name
, [], [buffer
]);
354 assertBufferClosed(name
, buffer
);
356 test : function (name
, e
) {
357 return e
.data
.length
== 0;
361 testList
= testList
.concat(allBufferTypes
.map(function(bufferType
) { return {
362 name
: "raw " + bufferType
[0],
363 send: function (name
) {
364 var view
= createView(bufferType
[1], bufferType
[2]);
365 wrapSend(name
, view
, [view
.buffer
]);
366 assertViewClosed(name
, view
);
367 assertBufferClosed(name
, view
.buffer
);
368 wrapFailSend(name
, view
, [view
.buffer
]);
369 wrapFailSend(name
, view
, []);
371 test: function (name
, e
) {
372 return checkView(name
, bufferType
[1], e
.data
) && checkEmptyArray(name
, e
.ports
);
377 function viewAndBuffer(viewFirst
, bufferType
) {
379 name
: (viewFirst
? "send view, buffer for " : "send buffer, view for ") + bufferType
[0],
380 send: function (name
) {
381 var view
= createView(bufferType
[1], bufferType
[2]);
382 var buffer
= view
.buffer
;
383 wrapSend(name
, viewFirst
? [view
, buffer
] : [buffer
, view
], [buffer
]);
384 assertViewClosed(name
, view
);
385 assertBufferClosed(name
, buffer
);
386 wrapFailSend(name
, view
, [buffer
]);
387 wrapFailSend(name
, view
, []);
388 wrapFailSend(name
, buffer
, [buffer
]);
389 wrapFailSend(name
, buffer
, []);
390 wrapFailSend(name
, [view
, buffer
], [buffer
]);
391 wrapFailSend(name
, [buffer
, view
], [buffer
]);
392 wrapFailSend(name
, [view
, buffer
], []);
393 wrapFailSend(name
, [buffer
, view
], []);
395 test: function (name
, e
) {
396 var view
= e
.data
[viewFirst
? 0 : 1];
397 var buffer
= e
.data
[viewFirst
? 1 : 0];
398 if (buffer
!== view
.buffer
) {
399 testFailed(name
+ " buffer not shared");
402 return checkView(name
, bufferType
[1], view
) && checkEmptyArray(name
, e
.ports
);
407 function squashUnrelatedViews(bufferType
) {
409 name
: "squash unrelated views for " + bufferType
[0],
410 send: function(name
) {
411 var view
= createView(bufferType
[1], bufferType
[2]);
412 var views
= createEveryView(view
.buffer
);
413 var buffer
= view
.buffer
;
414 wrapSend(name
, view
, [view
.buffer
]);
415 assertViewClosed(name
, view
);
416 assertBufferClosed(name
, view
.buffer
);
417 for (var v
= 0; v
< views
.length
; ++v
) {
418 assertViewClosed(name
+ "(view " + v
+ ")", views
[v
]);
420 wrapFailSend(name
, views
, [buffer
]);
422 test: function (name
, e
) { return checkView(name
, bufferType
[1], e
.data
) && checkEmptyArray(name
, e
.ports
); }
426 testList
= testList
.concat(allBufferTypes
.map(function(bufferType
) { return viewAndBuffer(true, bufferType
); }));
427 testList
= testList
.concat(allBufferTypes
.map(function(bufferType
) { return viewAndBuffer(false, bufferType
); }));
428 testList
= testList
.concat(allBufferTypes
.map(function(bufferType
) { return squashUnrelatedViews(bufferType
); }));
430 function doneTest() {
431 if (++window
.testsComplete
== testList
.length
) {
435 var t
= testList
[window
.testsComplete
];
439 testFailed(t
.name
+ ": on send: " + e
);
445 function windowHandleMessage(event
) {
446 var currentTest
= testList
[window
.testsComplete
];
447 if (currentTest
.alreadyHit
) {
448 testFailed(currentTest
.name
+ ": windowHandleMessage hit more than once.");
451 currentTest
.alreadyHit
= true;
453 if (currentTest
.test(currentTest
.name
, event
)) {
454 testPassed(currentTest
.name
);
457 testFailed(currentTest
.name
+ ": on recieve: " + e
+ ". event.data = " + event
.data
);
462 window
.addEventListener('message', windowHandleMessage
);
463 window
.testsComplete
= -1;
466 successfullyParsed
= true;