| <html> |
| <head> |
| <script src="../../resources/js-test.js"></script> |
| </head> |
| <body> |
| <script> |
| description("Tests various use cases when cloning MessagePorts."); |
| window.jsTestIsAsync = true; |
| |
| var channel = new MessageChannel; |
| channel.port1.onmessage = channel.port2.onmessage = function(evt) { |
| testFailed("Should not have received message: " + evt.data); |
| } |
| |
| // Posting port to itself should throw an exception. |
| shouldThrow("channel.port1.postMessage('msg', [channel.port1])", '"DataCloneError: Failed to execute \'postMessage\' on \'MessagePort\': Port at index 0 contains the source port."'); |
| |
| debug("Posting port to entangled pair neuters the port and does nothing else:"); |
| channel = new MessageChannel; |
| var channel2 = new MessageChannel; |
| channel.port1.postMessage("msg", [channel.port2]); |
| shouldThrow("channel2.port1.postMessage('msg', [channel.port2])", '"DataCloneError: Failed to execute \'postMessage\' on \'MessagePort\': Port at index 0 is already neutered."'); |
| |
| channel = new MessageChannel; |
| channel2 = new MessageChannel |
| channel.port1.postMessage("msg", [channel2.port1]); |
| |
| debug("Posting a detached ArrayBuffer should throw."); |
| channel = new MessageChannel; |
| var arrayBuffer = new ArrayBuffer(2); |
| |
| channel.port1.postMessage("msg", [arrayBuffer]); |
| shouldThrow("channel.port1.postMessage(arrayBuffer, [])", '"DataCloneError: Failed to execute \'postMessage\' on \'MessagePort\': An ArrayBuffer is detached and could not be cloned."'); |
| |
| debug("Posting a detached ArrayBufferView should throw."); |
| channel = new MessageChannel; |
| var uint16Array = new Uint16Array(10); |
| |
| shouldThrow("channel.port1.postMessage('msg', [uint16Array])", '"TypeError: Failed to execute \'postMessage\' on \'MessagePort\': Value at index 0 does not have a transferable type."'); |
| |
| channel.port1.postMessage("msg", [uint16Array.buffer]); |
| shouldThrow("channel.port1.postMessage(uint16Array, [])", '"DataCloneError: Failed to execute \'postMessage\' on \'MessagePort\': An ArrayBuffer is detached and could not be cloned."'); |
| |
| // Should not be able to post a cloned port. |
| shouldThrow("channel.port1.postMessage('msg', [channel2.port1])", '"DataCloneError: Failed to execute \'postMessage\' on \'MessagePort\': Port at index 0 is already neutered."'); |
| |
| // Test posting messages to a port in cloned state. |
| |
| var channel = new MessageChannel; |
| var channel2 = new MessageChannel; |
| |
| // Post messages before and after clone to make sure ordering is preserved and all messages are received. |
| channel2.port2.postMessage("1"); |
| channel.port1.postMessage("msg", [channel2.port1]); |
| channel2.port2.postMessage("2"); |
| channel2.port2.postMessage("3"); |
| var testEvent; |
| var messageIndex = 1; |
| channel.port2.onmessage = function(evt) { |
| testEvent = evt; |
| shouldBe("testEvent.ports.length", "1"); |
| evt.ports[0].onmessage = function(evt) { |
| testEvent = evt; |
| shouldBe("parseInt(testEvent.data)", "" + messageIndex); |
| messageIndex++; |
| if (messageIndex == 4) { |
| testPassed("Posted messages to cloned port."); |
| testDoublyClonedPort(); |
| } |
| } |
| } |
| |
| function testDoublyClonedPort() |
| { |
| var channel = new MessageChannel; |
| var channel2 = new MessageChannel; |
| channel.port1.postMessage("msg", [channel2.port1]); |
| channel.port2.postMessage("msg", [channel2.port2]); |
| gc(); |
| channel.port1.onmessage = function(evt) { |
| evt.ports[0].postMessage("testme"); |
| } |
| channel.port2.onmessage = function(evt) { |
| evt.ports[0].onmessage = function (evt) { |
| testEvent = evt; |
| shouldBe("testEvent.data", "'testme'"); |
| testPostClosePort(); |
| } |
| } |
| |
| } |
| |
| // *Should* be able to post a closed port. |
| function testPostClosePort() |
| { |
| var channel = new MessageChannel; |
| var channel2 = new MessageChannel; |
| channel2.port2.close(); |
| channel.port1.postMessage("closed", [channel2.port2]); |
| channel.port2.onmessage = function(evt) { |
| testEvent = evt; |
| shouldNotBe("testEvent.ports", "null"); |
| shouldBe("testEvent.ports.length", "1"); |
| shouldBe("testEvent.data", "'closed'"); |
| |
| finishJSTest(); |
| } |
| } |
| |
| </script> |
| </body> |
| </html> |