< prev index next >

tests/system/src/test/java/test/memoryleak/JSCallbackMemoryTest.java

Print this page




  70     private static final boolean VERBOSE = false;
  71 
  72     private static Stage primarystage;
  73 
  74     private boolean unexpectedCallback = false;
  75 
  76     private MyObject myObj = new MyObject();
  77 
  78     private Stage[] stages = new Stage[NUM_STAGES];
  79 
  80     private final Set<WeakReference<Object>> refs = new HashSet<>();
  81 
  82     private final boolean[] callbackStatus = new boolean[NUM_STAGES];
  83 
  84     private final WebView[] webviewArray = new WebView[NUM_STAGES];
  85 
  86     private final int[] primitiveArray = { 1, 2, 3, 4, 5 };
  87 
  88     private final Object[] objectArray = { new Object(), new Object(), new Object(), new Object() };
  89 


  90     public final class MyObject {
  91 
  92         // called from JavaScript
  93         public void jsobjcallback() {
  94             if (VERBOSE) {
  95                 System.err.println("Object...Callback from JavaScript!");
  96             }
  97             unexpectedCallback = true;
  98         }
  99     }
 100 
 101     public final class TestStage extends Stage {
 102 
 103         private int stageIndex = 0;
 104 
 105         TestStage(int index) {
 106             this.stageIndex = index;
 107         }
 108 
 109         // called from JavaScript


 203 
 204     @AfterClass
 205     public static void doTeardownOnce() {
 206         Platform.exit();
 207     }
 208 
 209     @After
 210     public void doTeardown() {
 211         Util.runAndWait(() -> {
 212             if (stages != null) {
 213                 for (int i = 0; i < NUM_STAGES; i++) {
 214                     if (stages[i].isShowing()) {
 215                         stages[i].hide();
 216                     }
 217                 }
 218                 stages = null;
 219             }
 220         });
 221     }
 222 


























 223     // ========================== TEST CASES ==========================
 224 
 225     @Test
 226     public void testJsCallbackLeak() throws Exception {

 227 
 228         Util.runAndWait(() -> {
 229 
 230             int stagePosition = 40;
 231             for (int i = 0; i < NUM_STAGES; i++) {
 232                 final Stage stage = new TestStage(i);
 233                 stages[i] = stage;
 234                 stage.setTitle("Stage " + i);
 235                 WebView webview = new WebView();
 236                 Scene scene = new Scene(webview);
 237                 scene.setFill(Color.LIGHTYELLOW);
 238                 stage.setX(stagePosition);
 239                 stage.setY(stagePosition);
 240                 stagePosition += OFFSET;
 241                 stage.setWidth(210);
 242                 stage.setHeight(180);
 243                 stage.setScene(scene);
 244 
 245                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 246                     if (n == Worker.State.SUCCEEDED) {

 247                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 248                         assertNotNull(window);
 249                         window.setMember("callback1", stage);





 250                     }
 251                 });
 252 
 253                 webview.getEngine().loadContent(html);
 254                 stage.show();
 255                 refs.add( new WeakReference<Object>(stage));
 256             }
 257         });
 258 
 259         Util.sleep(SLEEP_TIME);








 260 
 261         Util.runAndWait(() -> {
 262 
 263             for (int i = 0; i < NUM_STAGES; i++) {
 264                 stages[i].hide();
 265             }
 266             stages = null;
 267         });
 268 
 269 
 270         for (int j = 0; j < 2; j++) {
 271             System.gc();
 272             Util.sleep(SLEEP_TIME);
 273             Set<WeakReference<Object>> collected = new HashSet<>();
 274 
 275             for (WeakReference<Object> ref : refs) {
 276                 if (ref.get() == null) {
 277                     collected.add(ref);
 278                 }
 279             }
 280             refs.removeAll(collected);
 281 
 282             if (j == 0) {
 283                 // First time GC -> Collected will be equal to NUM_STAGES and refs size (remaining) will be 0
 284                 assertEquals(NUM_STAGES, collected.size());
 285                 assertEquals(0, refs.size());
 286             }
 287             else {
 288                 // Second time GC -> Collected will be 0 and refs size (remaining) will be 0
 289                 assertEquals(0, collected.size());
 290                 assertEquals(0, refs.size());
 291             }
 292         }
 293     }
 294 
 295     @Test
 296     public void testJsCallbackFunction() throws Exception {

 297 
 298         Util.runAndWait(() -> {
 299 
 300             int stagePosition = 40;
 301             for (int i = 0; i < NUM_STAGES; i++) {
 302                 final Stage stage = new TestStage(i);
 303                 stages[i] = stage;
 304                 stage.setTitle("Stage " + i);
 305                 WebView webview = new WebView();
 306                 Scene scene = new Scene(webview);
 307                 scene.setFill(Color.LIGHTYELLOW);
 308                 stage.setX(stagePosition);
 309                 stage.setY(stagePosition);
 310                 stagePosition += OFFSET;
 311                 stage.setWidth(210);
 312                 stage.setHeight(180);
 313                 stage.setScene(scene);
 314 
 315                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 316                     if (n == Worker.State.SUCCEEDED) {

 317                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 318                         assertNotNull(window);
 319                         window.setMember("callback1", stage);
 320                         webview.getEngine().executeScript("document.getElementById(\"mybtn1\").click()");





 321                     }
 322                 });
 323 
 324                 webview.getEngine().loadContent(html);
 325                 stage.show();
 326             }
 327         });
 328 
 329         Util.sleep(SLEEP_TIME);










 330         System.gc();
 331         for (int i = 0; i < NUM_STAGES; i++) {
 332             assertTrue(callbackStatus[i]);


 333         }





 334     }
 335 
 336     @Test
 337     public void testJsCallbackReleaseFunction() throws Exception {

 338 
 339         Util.runAndWait(() -> {
 340 
 341             int stagePosition = 40;
 342             for (int i = 0; i < NUM_STAGES; i++) {
 343                 final Stage stage = new TestStage(i);
 344                 stages[i] = stage;
 345                 stage.setTitle("Stage " + i);
 346                 WebView webview = new WebView();
 347                 Scene scene = new Scene(webview);
 348                 scene.setFill(Color.LIGHTYELLOW);
 349                 stage.setX(stagePosition);
 350                 stage.setY(stagePosition);
 351                 stagePosition += OFFSET;
 352                 stage.setWidth(210);
 353                 stage.setHeight(180);
 354                 stage.setScene(scene);
 355 
 356                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 357                     if (n == Worker.State.SUCCEEDED) {

 358                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 359                         assertNotNull(window);
 360                         window.setMember("callback1", stage);
 361                         window.setMember("callback4", myObj);
 362 
 363                         webview.getEngine().executeScript("document.getElementById(\"mybtn1\").click()");
 364 
 365                         // Below executeScript call will make myObj=null and GC'ed
 366                         webview.getEngine().executeScript("document.getElementById(\"mybtn3\").click()");
 367 
 368                         // Below executeScript call should not execute the JS callback (jsobjcallback) and should not cause crash as above executeScript just made myObj=null;
 369                         webview.getEngine().executeScript("document.getElementById(\"mybtn4\").click()");





 370                     }
 371                 });
 372 
 373                 webview.getEngine().loadContent(html);
 374                 stage.show();
 375             }
 376         });
 377 
 378         Util.sleep(SLEEP_TIME);










 379         System.gc();








 380 
 381         assertFalse(unexpectedCallback);
 382     }
 383 
 384     @Test
 385     public void testJsCallbackConsoleFunction() throws Exception {

 386 
 387         Util.runAndWait(() -> {
 388 
 389             int stagePosition = 40;
 390             for (int i = 0; i < NUM_STAGES; i++) {
 391                 final Stage stage = new TestStage(i);
 392                 stages[i] = stage;
 393                 stage.setTitle("Stage " + i);
 394                 WebView webview = new WebView();
 395                 Scene scene = new Scene(webview);
 396                 scene.setFill(Color.LIGHTYELLOW);
 397                 stage.setX(stagePosition);
 398                 stage.setY(stagePosition);
 399                 stagePosition += OFFSET;
 400                 stage.setWidth(210);
 401                 stage.setHeight(180);
 402                 stage.setScene(scene);
 403 
 404                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 405                     if (n == Worker.State.SUCCEEDED) {

 406                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 407                         assertNotNull(window);
 408 
 409                         window.setMember("console", new Object());
 410                         System.gc(); System.gc();

 411                         webview.getEngine().executeScript("window.console.debug = function() {}");





 412                     }
 413                 });
 414 
 415                 webview.getEngine().loadContent(html);
 416                 stage.show();
 417             }
 418         });
 419 
 420         Util.sleep(SLEEP_TIME);









 421         System.gc();

 422     }
 423 
 424     @Test
 425     public void testJsCallbackStrongRefPrimitiveArrayFunction() throws Exception {

 426 
 427         Util.runAndWait(() -> {
 428 
 429             int stagePosition = 40;
 430             for (int i = 0; i < NUM_STAGES; i++) {
 431                 final Stage stage = new TestStage(i);
 432                 stages[i] = stage;
 433                 stage.setTitle("Stage " + i);
 434                 WebView webview = new WebView();
 435                 Scene scene = new Scene(webview);
 436                 scene.setFill(Color.LIGHTYELLOW);
 437                 stage.setX(stagePosition);
 438                 stage.setY(stagePosition);
 439                 stagePosition += OFFSET;
 440                 stage.setWidth(210);
 441                 stage.setHeight(180);
 442                 stage.setScene(scene);
 443 
 444                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 445                     if (n == Worker.State.SUCCEEDED) {

 446                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 447                         assertNotNull(window);
 448                         window.setMember("callback2", stage);
 449                         window.setMember("primitiveArray", primitiveArray);
 450                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback2(primitiveArray);}");
 451                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").click()");





 452                     }
 453                 });
 454 
 455                 webview.getEngine().loadContent(html);
 456                 stage.show();
 457             }
 458         });
 459 
 460         Util.sleep(SLEEP_TIME);










 461         System.gc();
 462         for (int i = 0; i < NUM_STAGES; i++) {
 463             assertTrue(callbackStatus[i]);


 464         }





 465     }
 466 
 467     @Test
 468     public void testJsCallbackLocalPrimitiveArrayFunctionWithGC() throws Exception {


 469 
 470         Util.runAndWait(() -> {
 471 
 472             int[] localPrimitiveArray = {1, 2, 3, 4, 5};
 473             int stagePosition = 40;
 474             for (int i = 0; i < NUM_STAGES; i++) {
 475                 final Stage stage = new TestStage(i);
 476                 stages[i] = stage;
 477                 stage.setTitle("Stage " + i);
 478                 WebView webview = new WebView();
 479                 webviewArray[i] = webview;
 480                 Scene scene = new Scene(webview);
 481                 scene.setFill(Color.LIGHTYELLOW);
 482                 stage.setX(stagePosition);
 483                 stage.setY(stagePosition);
 484                 stagePosition += OFFSET;
 485                 stage.setWidth(210);
 486                 stage.setHeight(180);
 487                 stage.setScene(scene);
 488 
 489                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 490                     if (n == Worker.State.SUCCEEDED) {

 491                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 492                         assertNotNull(window);
 493                         window.setMember("callback2", stage);
 494                         window.setMember("localPrimitiveArray", new int[] { 1, 2, 3, 4, 5 });
 495                         System.gc(); System.gc();






 496                     }
 497                 });
 498 
 499                 webview.getEngine().loadContent(html);
 500                 stage.show();
 501             }
 502         });
 503 










 504         Util.sleep(SLEEP_TIME);
 505         System.gc();
 506 
 507         Util.runAndWait(() -> {
 508 
 509             for (int i = 0; i < NUM_STAGES; i++) {
 510                 System.gc();

 511                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback3(localPrimitiveArray);}");
 512                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
 513             }

 514         });
 515 






 516         assertFalse(unexpectedCallback);
 517     }
 518 
 519     @Test
 520     public void testJsCallbackStrongRefObjectArrayFunction() throws Exception {

 521 
 522         Util.runAndWait(() -> {
 523 
 524             int stagePosition = 40;
 525             for (int i = 0; i < NUM_STAGES; i++) {
 526                 final Stage stage = new TestStage(i);
 527                 stages[i] = stage;
 528                 stage.setTitle("Stage " + i);
 529                 WebView webview = new WebView();
 530                 Scene scene = new Scene(webview);
 531                 scene.setFill(Color.LIGHTYELLOW);
 532                 stage.setX(stagePosition);
 533                 stage.setY(stagePosition);
 534                 stagePosition += OFFSET;
 535                 stage.setWidth(210);
 536                 stage.setHeight(180);
 537                 stage.setScene(scene);
 538 
 539                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 540                     if (n == Worker.State.SUCCEEDED) {

 541                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 542                         assertNotNull(window);
 543                         window.setMember("callback2", stage);
 544                         window.setMember("objectArray", objectArray);
 545                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback4(objectArray);}");
 546                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").click()");





 547                     }
 548                 });
 549 
 550                 webview.getEngine().loadContent(html);
 551                 stage.show();
 552             }
 553         });
 554 
 555         Util.sleep(SLEEP_TIME);










 556         System.gc();
 557         for (int i = 0; i < NUM_STAGES; i++) {
 558             assertTrue(callbackStatus[i]);


 559         }






 560     }
 561 
 562     @Test
 563     public void testJsCallbackLocalObjectArrayFunctionWithGC() throws Exception {


 564 
 565         Util.runAndWait(() -> {
 566 
 567             int stagePosition = 40;
 568             for (int i = 0; i < NUM_STAGES; i++) {
 569                 final Stage stage = new TestStage(i);
 570                 stages[i] = stage;
 571                 stage.setTitle("Stage " + i);
 572                 WebView webview = new WebView();
 573                 webviewArray[i] = webview;
 574                 Scene scene = new Scene(webview);
 575                 scene.setFill(Color.LIGHTYELLOW);
 576                 stage.setX(stagePosition);
 577                 stage.setY(stagePosition);
 578                 stagePosition += OFFSET;
 579                 stage.setWidth(210);
 580                 stage.setHeight(180);
 581                 stage.setScene(scene);
 582 
 583                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 584                     if (n == Worker.State.SUCCEEDED) {

 585                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 586                         assertNotNull(window);
 587                         window.setMember("callback2", stage);
 588                         window.setMember("localObjectArray", new Object[] { new Object(), new Object(), new Object(), new Object() });
 589                         System.gc(); System.gc();






 590                     }
 591                 });
 592 
 593                 webview.getEngine().loadContent(html);
 594                 stage.show();
 595             }
 596         });
 597 










 598         Util.sleep(SLEEP_TIME);
 599         System.gc();
 600 
 601         Util.runAndWait(() -> {
 602 
 603             for (int i = 0; i < NUM_STAGES; i++) {
 604                 System.gc();

 605                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback5(localObjectArray);}");
 606                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
 607             }

 608         });






 609 
 610         assertFalse(unexpectedCallback);
 611     }
 612 }


  70     private static final boolean VERBOSE = false;
  71 
  72     private static Stage primarystage;
  73 
  74     private boolean unexpectedCallback = false;
  75 
  76     private MyObject myObj = new MyObject();
  77 
  78     private Stage[] stages = new Stage[NUM_STAGES];
  79 
  80     private final Set<WeakReference<Object>> refs = new HashSet<>();
  81 
  82     private final boolean[] callbackStatus = new boolean[NUM_STAGES];
  83 
  84     private final WebView[] webviewArray = new WebView[NUM_STAGES];
  85 
  86     private final int[] primitiveArray = { 1, 2, 3, 4, 5 };
  87 
  88     private final Object[] objectArray = { new Object(), new Object(), new Object(), new Object() };
  89 
  90     private AssertionError encounteredException = null;
  91 
  92     public final class MyObject {
  93 
  94         // called from JavaScript
  95         public void jsobjcallback() {
  96             if (VERBOSE) {
  97                 System.err.println("Object...Callback from JavaScript!");
  98             }
  99             unexpectedCallback = true;
 100         }
 101     }
 102 
 103     public final class TestStage extends Stage {
 104 
 105         private int stageIndex = 0;
 106 
 107         TestStage(int index) {
 108             this.stageIndex = index;
 109         }
 110 
 111         // called from JavaScript


 205 
 206     @AfterClass
 207     public static void doTeardownOnce() {
 208         Platform.exit();
 209     }
 210 
 211     @After
 212     public void doTeardown() {
 213         Util.runAndWait(() -> {
 214             if (stages != null) {
 215                 for (int i = 0; i < NUM_STAGES; i++) {
 216                     if (stages[i].isShowing()) {
 217                         stages[i].hide();
 218                     }
 219                 }
 220                 stages = null;
 221             }
 222         });
 223     }
 224 
 225     private boolean isAllStagesNull() {
 226         Set<WeakReference<Object>> collected = new HashSet<>();
 227 
 228         for (WeakReference<Object> ref : refs) {
 229             if (ref.get() != null) {
 230                 return false;
 231             }
 232             collected.add(ref);
 233         }
 234 
 235         refs.removeAll(collected);
 236 
 237         return true;
 238     }
 239 
 240     private boolean isAllCallbackStatusTrue() {
 241 
 242         for (int i = 0; i < NUM_STAGES; i++) {
 243             if (callbackStatus[i] == false) {
 244                 return false;
 245             }
 246         }
 247 
 248         return true;
 249     }
 250 
 251     // ========================== TEST CASES ==========================
 252 
 253     @Test
 254     public void testJsCallbackLeak() throws Exception {
 255         final CountDownLatch latch = new CountDownLatch(1);
 256 
 257         Util.runAndWait(() -> {
 258 
 259             int stagePosition = 40;
 260             for (int i = 0; i < NUM_STAGES; i++) {
 261                 final Stage stage = new TestStage(i);
 262                 stages[i] = stage;
 263                 stage.setTitle("Stage " + i);
 264                 WebView webview = new WebView();
 265                 Scene scene = new Scene(webview);
 266                 scene.setFill(Color.LIGHTYELLOW);
 267                 stage.setX(stagePosition);
 268                 stage.setY(stagePosition);
 269                 stagePosition += OFFSET;
 270                 stage.setWidth(210);
 271                 stage.setHeight(180);
 272                 stage.setScene(scene);
 273 
 274                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 275                     if (n == Worker.State.SUCCEEDED) {
 276                         try {
 277                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 278                             assertNotNull(window);
 279                             window.setMember("callback1", stage);
 280                         } catch(AssertionError ex) {
 281                             encounteredException = ex;
 282                         } finally {
 283                             latch.countDown();
 284                         }
 285                     }
 286                 });
 287 
 288                 webview.getEngine().loadContent(html);
 289                 stage.show();
 290                 refs.add( new WeakReference<Object>(stage));
 291             }
 292         });
 293 
 294         if (encounteredException != null) {
 295             throw encounteredException;
 296         }
 297 
 298         try {
 299             latch.await();
 300         } catch (InterruptedException ex) {
 301             throw new AssertionError(ex);
 302         }
 303 
 304         Util.runAndWait(() -> {
 305 
 306             for (int i = 0; i < NUM_STAGES; i++) {
 307                 stages[i].hide();
 308             }
 309             stages = null;
 310         });
 311 
 312 
 313         for (int j = 0; j < 5; j++) {
 314             System.gc();
 315             System.runFinalization();

 316 
 317             if (isAllStagesNull()) {
 318                 break;

 319             }


 320 
 321             Util.sleep(SLEEP_TIME);



 322         }



 323         assertEquals(0, refs.size());
 324     }


 325 
 326     @Test
 327     public void testJsCallbackFunction() throws Exception {
 328         final CountDownLatch latch = new CountDownLatch(1);
 329 
 330         Util.runAndWait(() -> {
 331 
 332             int stagePosition = 40;
 333             for (int i = 0; i < NUM_STAGES; i++) {
 334                 final Stage stage = new TestStage(i);
 335                 stages[i] = stage;
 336                 stage.setTitle("Stage " + i);
 337                 WebView webview = new WebView();
 338                 Scene scene = new Scene(webview);
 339                 scene.setFill(Color.LIGHTYELLOW);
 340                 stage.setX(stagePosition);
 341                 stage.setY(stagePosition);
 342                 stagePosition += OFFSET;
 343                 stage.setWidth(210);
 344                 stage.setHeight(180);
 345                 stage.setScene(scene);
 346 
 347                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 348                     if (n == Worker.State.SUCCEEDED) {
 349                         try {
 350                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 351                             assertNotNull(window);
 352                             window.setMember("callback1", stage);
 353                             webview.getEngine().executeScript("document.getElementById(\"mybtn1\").click()");
 354                         } catch(AssertionError ex) {
 355                             encounteredException = ex;
 356                         } finally {
 357                             latch.countDown();
 358                         }
 359                     }
 360                 });
 361 
 362                 webview.getEngine().loadContent(html);
 363                 stage.show();
 364             }
 365         });
 366 
 367         if (encounteredException != null) {
 368             throw encounteredException;
 369         }
 370 
 371         try {
 372             latch.await();
 373         } catch (InterruptedException ex) {
 374             throw new AssertionError(ex);
 375         }
 376 
 377         for (int j = 0; j < 5; j++) {
 378             System.gc();
 379             System.runFinalization();
 380 
 381             if (isAllCallbackStatusTrue()) {
 382                 break;
 383             }
 384 
 385             Util.sleep(SLEEP_TIME);
 386         }
 387 
 388         assertTrue("All Button Callback return true", isAllCallbackStatusTrue());
 389     }
 390 
 391     @Test
 392     public void testJsCallbackReleaseFunction() throws Exception {
 393         final CountDownLatch latch = new CountDownLatch(1);
 394 
 395         Util.runAndWait(() -> {
 396 
 397             int stagePosition = 40;
 398             for (int i = 0; i < NUM_STAGES; i++) {
 399                 final Stage stage = new TestStage(i);
 400                 stages[i] = stage;
 401                 stage.setTitle("Stage " + i);
 402                 WebView webview = new WebView();
 403                 Scene scene = new Scene(webview);
 404                 scene.setFill(Color.LIGHTYELLOW);
 405                 stage.setX(stagePosition);
 406                 stage.setY(stagePosition);
 407                 stagePosition += OFFSET;
 408                 stage.setWidth(210);
 409                 stage.setHeight(180);
 410                 stage.setScene(scene);
 411 
 412                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 413                     if (n == Worker.State.SUCCEEDED) {
 414                         try {
 415                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 416                             assertNotNull(window);
 417                             window.setMember("callback1", stage);
 418                             window.setMember("callback4", myObj);
 419 
 420                             webview.getEngine().executeScript("document.getElementById(\"mybtn1\").click()");
 421 
 422                             // Below executeScript call will make myObj=null and GC'ed
 423                             webview.getEngine().executeScript("document.getElementById(\"mybtn3\").click()");
 424 
 425                             // Below executeScript call should not execute the JS callback (jsobjcallback) and should not cause crash as above executeScript just made myObj=null;
 426                             webview.getEngine().executeScript("document.getElementById(\"mybtn4\").click()");
 427                         } catch(AssertionError ex) {
 428                             encounteredException = ex;
 429                         } finally {
 430                             latch.countDown();
 431                         }
 432                     }
 433                 });
 434 
 435                 webview.getEngine().loadContent(html);
 436                 stage.show();
 437             }
 438         });
 439 
 440         if (encounteredException != null) {
 441             throw encounteredException;
 442         }
 443 
 444         try {
 445             latch.await();
 446         } catch (InterruptedException ex) {
 447             throw new AssertionError(ex);
 448         }
 449 
 450         for (int j = 0; j < 5; j++) {
 451             System.gc();
 452             System.runFinalization();
 453 
 454             if (unexpectedCallback) {
 455                 break;
 456             }
 457 
 458             Util.sleep(SLEEP_TIME);
 459         }
 460 
 461         assertFalse(unexpectedCallback);
 462     }
 463 
 464     @Test
 465     public void testJsCallbackConsoleFunction() throws Exception {
 466         final CountDownLatch latch = new CountDownLatch(1);
 467 
 468         Util.runAndWait(() -> {
 469 
 470             int stagePosition = 40;
 471             for (int i = 0; i < NUM_STAGES; i++) {
 472                 final Stage stage = new TestStage(i);
 473                 stages[i] = stage;
 474                 stage.setTitle("Stage " + i);
 475                 WebView webview = new WebView();
 476                 Scene scene = new Scene(webview);
 477                 scene.setFill(Color.LIGHTYELLOW);
 478                 stage.setX(stagePosition);
 479                 stage.setY(stagePosition);
 480                 stagePosition += OFFSET;
 481                 stage.setWidth(210);
 482                 stage.setHeight(180);
 483                 stage.setScene(scene);
 484 
 485                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 486                     if (n == Worker.State.SUCCEEDED) {
 487                         try {
 488                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 489                             assertNotNull(window);
 490 
 491                             window.setMember("console", new Object());
 492                             System.gc(); System.gc();
 493                             System.runFinalization();
 494                             webview.getEngine().executeScript("window.console.debug = function() {}");
 495                         } catch(AssertionError ex) {
 496                             encounteredException = ex;
 497                         } finally {
 498                             latch.countDown();
 499                         }
 500                     }
 501                 });
 502 
 503                 webview.getEngine().loadContent(html);
 504                 stage.show();
 505             }
 506         });
 507 
 508         if (encounteredException != null) {
 509             throw encounteredException;
 510         }
 511 
 512         try {
 513             latch.await();
 514         } catch (InterruptedException ex) {
 515             throw new AssertionError(ex);
 516         }
 517 
 518         System.gc();
 519         System.runFinalization();
 520     }
 521 
 522     @Test
 523     public void testJsCallbackStrongRefPrimitiveArrayFunction() throws Exception {
 524         final CountDownLatch latch = new CountDownLatch(1);
 525 
 526         Util.runAndWait(() -> {
 527 
 528             int stagePosition = 40;
 529             for (int i = 0; i < NUM_STAGES; i++) {
 530                 final Stage stage = new TestStage(i);
 531                 stages[i] = stage;
 532                 stage.setTitle("Stage " + i);
 533                 WebView webview = new WebView();
 534                 Scene scene = new Scene(webview);
 535                 scene.setFill(Color.LIGHTYELLOW);
 536                 stage.setX(stagePosition);
 537                 stage.setY(stagePosition);
 538                 stagePosition += OFFSET;
 539                 stage.setWidth(210);
 540                 stage.setHeight(180);
 541                 stage.setScene(scene);
 542 
 543                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 544                     if (n == Worker.State.SUCCEEDED) {
 545                         try {
 546                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 547                             assertNotNull(window);
 548                             window.setMember("callback2", stage);
 549                             window.setMember("primitiveArray", primitiveArray);
 550                             webview.getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback2(primitiveArray);}");
 551                             webview.getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
 552                         } catch(AssertionError ex) {
 553                             encounteredException = ex;
 554                         } finally {
 555                             latch.countDown();
 556                         }
 557                     }
 558                 });
 559 
 560                 webview.getEngine().loadContent(html);
 561                 stage.show();
 562             }
 563         });
 564 
 565         if (encounteredException != null) {
 566             throw encounteredException;
 567         }
 568 
 569         try {
 570             latch.await();
 571         } catch (InterruptedException ex) {
 572             throw new AssertionError(ex);
 573         }
 574 
 575         for (int j = 0; j < 5; j++) {
 576             System.gc();
 577             System.runFinalization();
 578 
 579             if (isAllCallbackStatusTrue()) {
 580                 break;
 581             }
 582 
 583             Util.sleep(SLEEP_TIME);
 584         }
 585 
 586         assertTrue("All Button Callback return true", isAllCallbackStatusTrue());
 587     }
 588 
 589     @Test
 590     public void testJsCallbackLocalPrimitiveArrayFunctionWithGC() throws Exception {
 591         final CountDownLatch latch1 = new CountDownLatch(1);
 592         final CountDownLatch latch2 = new CountDownLatch(1);
 593 
 594         Util.runAndWait(() -> {
 595 
 596             int[] localPrimitiveArray = {1, 2, 3, 4, 5};
 597             int stagePosition = 40;
 598             for (int i = 0; i < NUM_STAGES; i++) {
 599                 final Stage stage = new TestStage(i);
 600                 stages[i] = stage;
 601                 stage.setTitle("Stage " + i);
 602                 WebView webview = new WebView();
 603                 webviewArray[i] = webview;
 604                 Scene scene = new Scene(webview);
 605                 scene.setFill(Color.LIGHTYELLOW);
 606                 stage.setX(stagePosition);
 607                 stage.setY(stagePosition);
 608                 stagePosition += OFFSET;
 609                 stage.setWidth(210);
 610                 stage.setHeight(180);
 611                 stage.setScene(scene);
 612 
 613                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 614                     if (n == Worker.State.SUCCEEDED) {
 615                         try {
 616                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 617                             assertNotNull(window);
 618                             window.setMember("callback2", stage);
 619                             window.setMember("localPrimitiveArray", new int[] { 1, 2, 3, 4, 5 });
 620                             System.gc(); System.gc();
 621                             System.runFinalization();
 622                         } catch(AssertionError ex) {
 623                             encounteredException = ex;
 624                         } finally {
 625                             latch1.countDown();
 626                         }
 627                     }
 628                 });
 629 
 630                 webview.getEngine().loadContent(html);
 631                 stage.show();
 632             }
 633         });
 634 
 635         if (encounteredException != null) {
 636             throw encounteredException;
 637         }
 638 
 639         try {
 640             latch1.await();
 641         } catch (InterruptedException ex) {
 642             throw new AssertionError(ex);
 643         }
 644 
 645         Util.sleep(SLEEP_TIME);

 646 
 647         Util.runAndWait(() -> {
 648 
 649             for (int i = 0; i < NUM_STAGES; i++) {
 650                 System.gc();
 651                 System.runFinalization();
 652                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback3(localPrimitiveArray);}");
 653                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
 654             }
 655             latch2.countDown();
 656         });
 657 
 658         try {
 659             latch2.await();
 660         } catch (InterruptedException ex) {
 661             throw new AssertionError(ex);
 662         }
 663 
 664         assertFalse(unexpectedCallback);
 665     }
 666 
 667     @Test
 668     public void testJsCallbackStrongRefObjectArrayFunction() throws Exception {
 669         final CountDownLatch latch = new CountDownLatch(1);
 670 
 671         Util.runAndWait(() -> {
 672 
 673             int stagePosition = 40;
 674             for (int i = 0; i < NUM_STAGES; i++) {
 675                 final Stage stage = new TestStage(i);
 676                 stages[i] = stage;
 677                 stage.setTitle("Stage " + i);
 678                 WebView webview = new WebView();
 679                 Scene scene = new Scene(webview);
 680                 scene.setFill(Color.LIGHTYELLOW);
 681                 stage.setX(stagePosition);
 682                 stage.setY(stagePosition);
 683                 stagePosition += OFFSET;
 684                 stage.setWidth(210);
 685                 stage.setHeight(180);
 686                 stage.setScene(scene);
 687 
 688                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 689                     if (n == Worker.State.SUCCEEDED) {
 690                         try {
 691                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 692                             assertNotNull(window);
 693                             window.setMember("callback2", stage);
 694                             window.setMember("objectArray", objectArray);
 695                             webview.getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback4(objectArray);}");
 696                             webview.getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
 697                         } catch(AssertionError ex) {
 698                             encounteredException = ex;
 699                         } finally {
 700                             latch.countDown();
 701                         }
 702                     }
 703                 });
 704 
 705                 webview.getEngine().loadContent(html);
 706                 stage.show();
 707             }
 708         });
 709 
 710         if (encounteredException != null) {
 711             throw encounteredException;
 712         }
 713 
 714         try {
 715             latch.await();
 716         } catch (InterruptedException ex) {
 717             throw new AssertionError(ex);
 718         }
 719 
 720         for (int j = 0; j < 5; j++) {
 721             System.gc();
 722             System.runFinalization();
 723 
 724             if (isAllCallbackStatusTrue()) {
 725                 break;
 726             }
 727 
 728             Util.sleep(SLEEP_TIME);
 729         }
 730 
 731         assertTrue("All Button Callback return true", isAllCallbackStatusTrue());
 732 
 733     }
 734 
 735     @Test
 736     public void testJsCallbackLocalObjectArrayFunctionWithGC() throws Exception {
 737         final CountDownLatch latch1 = new CountDownLatch(1);
 738         final CountDownLatch latch2 = new CountDownLatch(1);
 739 
 740         Util.runAndWait(() -> {
 741 
 742             int stagePosition = 40;
 743             for (int i = 0; i < NUM_STAGES; i++) {
 744                 final Stage stage = new TestStage(i);
 745                 stages[i] = stage;
 746                 stage.setTitle("Stage " + i);
 747                 WebView webview = new WebView();
 748                 webviewArray[i] = webview;
 749                 Scene scene = new Scene(webview);
 750                 scene.setFill(Color.LIGHTYELLOW);
 751                 stage.setX(stagePosition);
 752                 stage.setY(stagePosition);
 753                 stagePosition += OFFSET;
 754                 stage.setWidth(210);
 755                 stage.setHeight(180);
 756                 stage.setScene(scene);
 757 
 758                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
 759                     if (n == Worker.State.SUCCEEDED) {
 760                         try {
 761                             final JSObject window = (JSObject) webview.getEngine().executeScript("window");
 762                             assertNotNull(window);
 763                             window.setMember("callback2", stage);
 764                             window.setMember("localObjectArray", new Object[] { new Object(), new Object(), new Object(), new Object() });
 765                             System.gc(); System.gc();
 766                             System.runFinalization();
 767                         } catch(AssertionError ex) {
 768                             encounteredException = ex;
 769                         } finally {
 770                             latch1.countDown();
 771                         }
 772                     }
 773                 });
 774 
 775                 webview.getEngine().loadContent(html);
 776                 stage.show();
 777             }
 778         });
 779 
 780         if (encounteredException != null) {
 781             throw encounteredException;
 782         }
 783 
 784         try {
 785             latch1.await();
 786         } catch (InterruptedException ex) {
 787             throw new AssertionError(ex);
 788         }
 789 
 790         Util.sleep(SLEEP_TIME);

 791 
 792         Util.runAndWait(() -> {
 793 
 794             for (int i = 0; i < NUM_STAGES; i++) {
 795                 System.gc();
 796                 System.runFinalization();
 797                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback5(localObjectArray);}");
 798                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
 799             }
 800             latch2.countDown();
 801         });
 802 
 803         try {
 804             latch2.await();
 805         } catch (InterruptedException ex) {
 806             throw new AssertionError(ex);
 807         }
 808 
 809         assertFalse(unexpectedCallback);
 810     }
 811 }
< prev index next >