| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // Test the Worker API of d8. This test only makes sense with d8. A Worker |
| // spawns a new OS thread and isolate, and runs it concurrently with the |
| // current running thread. |
| |
| var workerScript = |
| `postMessage('Starting worker'); |
| // Set a global variable; should not be visible outside of the worker's |
| // context. |
| foo = 100; |
| var c = 0; |
| onmessage = function(m) { |
| switch (c++) { |
| case 0: |
| if (m !== undefined) throw new Error('undefined'); |
| break; |
| case 1: |
| if (m !== null) throw new Error('null'); |
| break; |
| case 2: |
| if (m !== true) throw new Error('true'); |
| break; |
| case 3: |
| if (m !== false) throw new Error('false'); |
| break; |
| case 4: |
| if (m !== 100) throw new Error('Number'); |
| break; |
| case 5: |
| if (m !== 'hi') throw new Error('String'); |
| break; |
| case 6: |
| if (JSON.stringify(m) !== '[4,true,\"bye\"]') { |
| throw new Error('Array'); |
| } |
| break; |
| case 7: |
| if (JSON.stringify(m) !== '{"a":1,"b":2.5,"c":"three"}') |
| throw new Error('Object' + JSON.stringify(m)); |
| break; |
| case 8: |
| var ab = m; |
| var t = new Uint32Array(ab); |
| if (ab.byteLength !== 16) |
| throw new Error('ArrayBuffer clone byteLength'); |
| for (var i = 0; i < 4; ++i) |
| if (t[i] !== i) |
| throw new Error('ArrayBuffer clone value ' + i); |
| break; |
| case 9: |
| var ab = m; |
| var t = new Uint32Array(ab); |
| if (ab.byteLength !== 32) |
| throw new Error('ArrayBuffer transfer byteLength'); |
| for (var i = 0; i < 8; ++i) |
| if (t[i] !== i) |
| throw new Error('ArrayBuffer transfer value ' + i); |
| break; |
| } |
| if (c == 10) { |
| postMessage('DONE'); |
| } |
| };`; |
| |
| if (this.Worker) { |
| function createArrayBuffer(byteLength) { |
| var ab = new ArrayBuffer(byteLength); |
| var t = new Uint32Array(ab); |
| for (var i = 0; i < byteLength / 4; ++i) |
| t[i] = i; |
| return ab; |
| } |
| |
| assertThrows(function() { |
| // Second arg must be 'options' object |
| new Worker(workerScript, 123); |
| }); |
| |
| assertThrows(function() { |
| new Worker('test/mjsunit/d8/d8-worker.js', {type: 'invalid'}); |
| }); |
| |
| assertThrows(function() { |
| // worker type defaults to 'classic' which tries to load from file |
| new Worker(workerScript); |
| }); |
| |
| var w = new Worker(workerScript, {type: 'string'}); |
| |
| assertEquals("Starting worker", w.getMessage()); |
| |
| w.postMessage(undefined); |
| w.postMessage(null); |
| w.postMessage(true); |
| w.postMessage(false); |
| w.postMessage(100); |
| w.postMessage("hi"); |
| w.postMessage([4, true, "bye"]); |
| w.postMessage({a: 1, b: 2.5, c: "three"}); |
| |
| // Test bad get in transfer list. |
| var transferList = [undefined]; |
| Object.defineProperty(transferList, '0', { |
| get: function() { |
| throw 'unexpected!'; |
| } |
| }); |
| assertThrows(function() { |
| w.postMessage([], transferList); |
| }); |
| |
| // Test console.log in transfer list. |
| (function() { |
| var val = [undefined]; |
| Object.defineProperty(val, '0', {get: () => console.log()}); |
| assertThrows(function() { |
| w.postMessage(val, [val]); |
| }); |
| })(); |
| |
| // Clone ArrayBuffer |
| var ab1 = createArrayBuffer(16); |
| w.postMessage(ab1); |
| assertEquals(16, ab1.byteLength); // ArrayBuffer should not be neutered. |
| |
| // Transfer ArrayBuffer |
| var ab2 = createArrayBuffer(32); |
| w.postMessage(ab2, [ab2]); |
| assertEquals(0, ab2.byteLength); // ArrayBuffer should be neutered. |
| |
| // Attempting to transfer the same ArrayBuffer twice should throw. |
| assertThrows(function() { |
| var ab3 = createArrayBuffer(4); |
| w.postMessage(ab3, [ab3, ab3]); |
| }); |
| |
| assertEquals("undefined", typeof foo); |
| |
| // Read a message from the worker. |
| assertEquals("DONE", w.getMessage()); |
| |
| w.terminate(); |
| |
| |
| // Make sure that the main thread doesn't block forever in getMessage() if |
| // the worker dies without posting a message. |
| var w2 = new Worker('', {type: 'string'}); |
| var msg = w2.getMessage(); |
| assertEquals(undefined, msg); |
| } |