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 } |