@@ -201,6 +201,100 @@ describe("Messaging runtime edges", function () {
201201 } ) ;
202202 } ) ;
203203
204+ // The MessageEvent constructor defaults an undefined `data` to null, as Web
205+ // IDL requires of its init dictionary. A delivered message is not built
206+ // from a dictionary: it carries whatever the payload deserialized to.
207+ describe ( "undefined payloads" , function ( ) {
208+ var payloads = [ undefined , null , false , 0 , "" ] ;
209+ // Closed after every spec, so one that failed or timed out leaves no
210+ // worker or channel behind. terminate() and close() are idempotent.
211+ var cleanups = [ ] ;
212+ afterEach ( function ( ) {
213+ cleanups . forEach ( function ( cleanup ) { cleanup ( ) ; } ) ;
214+ cleanups = [ ] ;
215+ } ) ;
216+
217+ // fail() throws in this runner, which would skip done() when called
218+ // from an event handler.
219+ function failOnWorkerError ( done ) {
220+ return function ( error ) {
221+ expect ( "worker error: " + error . message ) . toBeNull ( ) ;
222+ done ( ) ;
223+ } ;
224+ }
225+
226+ function expectPayloads ( events ) {
227+ expect ( events . map ( function ( event ) { return event . data ; } ) ) . toEqual ( payloads ) ;
228+ expect ( events [ 0 ] . data ) . toBeUndefined ( ) ;
229+ expect ( "data" in events [ 0 ] ) . toBe ( true ) ;
230+ }
231+
232+ it ( "arrive unchanged on a MessagePort" , function ( done ) {
233+ var channel = new MessageChannel ( ) ;
234+ // The receiver first: closing only the sender queues the close
235+ // behind the messages, which would still be delivered.
236+ cleanups . push ( function ( ) { channel . port2 . close ( ) ; channel . port1 . close ( ) ; } ) ;
237+ var events = [ ] ;
238+ channel . port2 . onmessage = function ( event ) {
239+ events . push ( event ) ;
240+ if ( events . length === payloads . length ) {
241+ expectPayloads ( events ) ;
242+ done ( ) ;
243+ }
244+ } ;
245+ payloads . forEach ( function ( payload ) { channel . port1 . postMessage ( payload ) ; } ) ;
246+ } ) ;
247+
248+ it ( "arrive unchanged on a BroadcastChannel" , function ( done ) {
249+ var sender = new BroadcastChannel ( "undefined-payloads" ) ;
250+ var receiver = new BroadcastChannel ( "undefined-payloads" ) ;
251+ cleanups . push ( function ( ) { sender . close ( ) ; receiver . close ( ) ; } ) ;
252+ var events = [ ] ;
253+ receiver . onmessage = function ( event ) {
254+ events . push ( event ) ;
255+ if ( events . length === payloads . length ) {
256+ expectPayloads ( events ) ;
257+ done ( ) ;
258+ }
259+ } ;
260+ payloads . forEach ( function ( payload ) { sender . postMessage ( payload ) ; } ) ;
261+ } ) ;
262+
263+ it ( "arrive unchanged in a worker and back on its Worker object" , function ( done ) {
264+ var worker = new Worker ( "./messaging/describeDataWorker.js" ) ;
265+ cleanups . push ( function ( ) { worker . terminate ( ) ; } ) ;
266+ var events = [ ] ;
267+ worker . onmessage = function ( event ) {
268+ events . push ( event ) ;
269+ if ( events . length === 2 ) {
270+ expect ( events [ 0 ] . data ) . toEqual ( { received : "undefined" } ) ;
271+ expect ( events [ 1 ] . data ) . toBeUndefined ( ) ;
272+ expect ( "data" in events [ 1 ] ) . toBe ( true ) ;
273+ done ( ) ;
274+ }
275+ } ;
276+ worker . onerror = failOnWorkerError ( done ) ;
277+ worker . postMessage ( undefined ) ;
278+ } ) ;
279+
280+ it ( "arrive unchanged on a node:worker_threads parentPort" , function ( done ) {
281+ var wt = require ( "node:worker_threads" ) ;
282+ var worker = new wt . Worker ( "~/tests/messaging/parentPortDescribeWorker.js" ) ;
283+ cleanups . push ( function ( ) { worker . terminate ( ) ; } ) ;
284+ worker . on ( "message" , function ( value ) {
285+ expect ( value ) . toEqual ( { received : "undefined" } ) ;
286+ done ( ) ;
287+ } ) ;
288+ worker . on ( "error" , failOnWorkerError ( done ) ) ;
289+ worker . postMessage ( undefined ) ;
290+ } ) ;
291+
292+ it ( "still default to null in a constructed MessageEvent" , function ( ) {
293+ expect ( new MessageEvent ( "message" ) . data ) . toBeNull ( ) ;
294+ expect ( new MessageEvent ( "message" , { data : undefined } ) . data ) . toBeNull ( ) ;
295+ } ) ;
296+ } ) ;
297+
204298 describe ( "worker error reporting" , function ( ) {
205299 // A worker boots on its own thread, so the first error arrives whenever
206300 // the runner gets to it; specs wait for it and only then settle for
0 commit comments