11describe ( "TNS Workers" , ( ) => {
2+ let expectedAliveRuntimes = 1 ; // Main thread's TNSRuntime
23 var originalTimeout ;
34 var DEFAULT_TIMEOUT_BEFORE_ASSERT = 500 ;
45
@@ -26,6 +27,7 @@ describe("TNS Workers", () => {
2627 worker . postMessage ( { eval : "postMessage(self === global);" } ) ;
2728 worker . onmessage = ( msg ) => {
2829 expect ( msg . data ) . toBe ( true ) ;
30+ worker . terminate ( ) ;
2931 done ( ) ;
3032 } ;
3133 } ) ;
@@ -39,6 +41,7 @@ describe("TNS Workers", () => {
3941 var worker = new Worker ( "./idonot-exist.js" ) ;
4042 worker . onerror = ( e ) => {
4143 expect ( e ) . not . toEqual ( null ) ;
44+ worker . terminate ( ) ;
4245 done ( ) ;
4346 }
4447 } ) ;
@@ -318,6 +321,7 @@ describe("TNS Workers", () => {
318321 setTimeout ( ( ) => {
319322 expect ( onerrorCounter ) . toBe ( 2 ) ;
320323 expect ( onmessageCounter ) . toBe ( 1 ) ;
324+ worker . terminate ( ) ;
321325 done ( ) ;
322326 } , DEFAULT_TIMEOUT_BEFORE_ASSERT ) ;
323327 } ) ;
@@ -354,12 +358,19 @@ describe("TNS Workers", () => {
354358
355359 it ( "Should not throw or crash when executing too much JS inside Worker" , ( done ) => {
356360 var worker = new Worker ( "./WorkerStressJSTest.js" ) ;
361+ // Worker is not guaranteed to have finished before the check for runtimes leak, so track it manually
362+ expectedAliveRuntimes ++ ;
357363 // the specific worker will post a message if something isn't right
358364 worker . onmessage = ( msg ) => {
359- worker . terminate ( ) ;
360- done ( "Exception is thrown in the web worker: " + msg ) ;
365+ // Worker sends this message when it finishes successfully
366+ expectedAliveRuntimes -- ;
367+ if ( msg . data !== "end" ) {
368+ worker . terminate ( ) ;
369+ done ( "Exception is thrown in the web worker: " + msg ) ;
370+ }
361371 }
362372 worker . onerror = ( e ) => {
373+ expectedAliveRuntimes -- ;
363374 worker . terminate ( ) ;
364375 done ( "Exception is thrown in the web worker: " + e ) ;
365376 }
@@ -383,13 +394,13 @@ describe("TNS Workers", () => {
383394 gC ( ) ;
384395
385396 setTimeout ( ( ) => {
397+ expectedAliveRuntimes ++ ; // This nature of this test prevents us from closing the worker (we need not store a reference to it)
386398 expect ( onmessageCalled ) . toBe ( true ) ;
387399 done ( ) ;
388400 } , DEFAULT_TIMEOUT_BEFORE_ASSERT ) ;
389401 } ) ;
390402
391403 it ( "Test worker should close and not receive messages after close() call" , ( done ) => {
392- var messageReceived = false ;
393404 var worker = new Worker ( "./EvalWorker.js" ) ;
394405
395406 worker . postMessage ( {
@@ -469,6 +480,55 @@ describe("TNS Workers", () => {
469480 } , DEFAULT_TIMEOUT_BEFORE_ASSERT ) ;
470481 } ) ;
471482
483+ if ( global . NSObject ) { // platform is iOS
484+ it ( "no crash during or after runtime teardown on iOS" , ( done ) => {
485+ // reduce number of workers on older (32-bit devices) to avoid sporadic failures due to timeout
486+ const numWorkers = ( interop . sizeof ( interop . types . id ) == 4 ) ? 4 : 10 ;
487+ const timeout = DEFAULT_TIMEOUT_BEFORE_ASSERT * 3.5 ;
488+
489+ let messageProducerTimeout = null ;
490+ let iteration = 0 ;
491+ const produceMessageInLoop = ( ) => {
492+ NSNotificationCenter . defaultCenter . postNotificationNameObjectUserInfo ( 'send-to-worker' , { iteration } , null ) ;
493+ iteration ++ ;
494+ messageProducerTimeout = setTimeout ( produceMessageInLoop , 1 ) ;
495+ } ;
496+ produceMessageInLoop ( ) ;
497+
498+ let onCloseEvents = 0 ;
499+ let onStartEvents = 0 ;
500+ for ( let i = 0 ; i < numWorkers ; i ++ ) { ;
501+ const worker = new Worker ( "./TeardownCrashWorker.js" ) ;
502+ worker . onmessage = ( msg ) => {
503+ if ( msg . data === "closing" ) {
504+ onCloseEvents ++ ;
505+ }
506+ else if ( msg . data === "starting" ) {
507+ onStartEvents ++ ;
508+ worker . postMessage ( i ) ;
509+ }
510+ }
511+ }
512+
513+ setTimeout ( ( ) => {
514+ clearTimeout ( messageProducerTimeout ) ;
515+
516+ expect ( onStartEvents ) . toBeGreaterThan ( 0 , `At least 1 worker should have started in ${ timeout } ms` ) ;
517+ expect ( onCloseEvents ) . toBeGreaterThan ( 0 , `At least 1 worker should have finished in ${ timeout } ms` ) ;
518+ done ( ) ;
519+ } , timeout ) ;
520+ } ) ;
521+
522+ it ( "Check for leaked runtimes" , function ( done ) {
523+ setTimeout ( ( ) => {
524+ const runtimesCount = TNSRuntime . runtimes ( ) . count ;
525+ expect ( runtimesCount ) . toBe ( expectedAliveRuntimes , `Found ${ runtimesCount } runtimes alive. Expected ${ expectedAliveRuntimes } .` ) ;
526+ done ( ) ;
527+ } , 1000 ) ;
528+ } ) ;
529+
530+ } // platform is iOS
531+
472532 function generateRandomString ( strLen ) {
473533 var chars = "abcAbc defgDEFG 1234567890 " ;
474534 var len = chars . length ;
0 commit comments