66using System . Dynamic ;
77using System . Globalization ;
88using System . Threading . Tasks ;
9+ using CefSharp . Example ;
910using Xunit ;
1011using Xunit . Abstractions ;
1112
@@ -23,6 +24,74 @@ public JavascriptCallbackTests(ITestOutputHelper output, CefSharpFixture collect
2324 this . collectionFixture = collectionFixture ;
2425 }
2526
27+ [ Fact ]
28+ public async Task ShouldCancelAfterV8ContextChange ( )
29+ {
30+ IJavascriptCallback callbackExecuteCancelAfterDisposeCallback ;
31+ Task callbackExecuteCancelAfterDisposeTask ;
32+ using ( var browser = new CefSharp . OffScreen . ChromiumWebBrowser ( automaticallyCreateBrowser : false ) )
33+ {
34+ await browser . CreateBrowserAsync ( ) ;
35+
36+ // no V8 context
37+ var withoutV8ContextException = await Assert . ThrowsAsync < Exception > ( ( ) => browser . EvaluateScriptAsync ( "(function() { return 1+1; })" ) ) ;
38+ Assert . StartsWith ( "Unable to execute javascript at this time" , withoutV8ContextException . Message ) ;
39+
40+ Task < JavascriptResponse > callbackExecuteWithoutV8ContextTask ;
41+ using ( var frame = browser . GetMainFrame ( ) )
42+ {
43+ callbackExecuteWithoutV8ContextTask = frame . EvaluateScriptAsync ( "(function() { return 1+2; })" ) ;
44+ }
45+
46+ // V8 context
47+ await browser . LoadUrlAsync ( CefExample . HelloWorldUrl ) ;
48+
49+ var callbackExecuteWithoutV8ContextResponse = await callbackExecuteWithoutV8ContextTask ;
50+ Assert . True ( callbackExecuteWithoutV8ContextResponse . Success ) ;
51+ var callbackExecuteWithoutV8ContextCallback = ( IJavascriptCallback ) callbackExecuteWithoutV8ContextResponse . Result ;
52+ var callbackExecuteWithoutV8ContextExecuteResponse = await callbackExecuteWithoutV8ContextCallback . ExecuteAsync ( ) ;
53+ Assert . True ( callbackExecuteWithoutV8ContextExecuteResponse . Success ) ;
54+ Assert . Equal ( 3 , callbackExecuteWithoutV8ContextExecuteResponse . Result ) ;
55+
56+ var callbackExecuteCancelAfterV8ContextResponse = await browser . EvaluateScriptAsync ( "(function() { return new Promise(resolve => setTimeout(resolve, 1000)); })" ) ;
57+ Assert . True ( callbackExecuteCancelAfterV8ContextResponse . Success ) ;
58+ var callbackExecuteCancelAfterV8ContextCallback = ( IJavascriptCallback ) callbackExecuteCancelAfterV8ContextResponse . Result ;
59+ var callbackExecuteCancelAfterV8ContextTask = callbackExecuteCancelAfterV8ContextCallback . ExecuteAsync ( ) ;
60+
61+ // change V8 context
62+ await browser . LoadUrlAsync ( CefExample . HelloWorldUrl ) ;
63+
64+ await Assert . ThrowsAsync < TaskCanceledException > ( ( ) => callbackExecuteCancelAfterV8ContextTask ) ;
65+ var callbackExecuteCancelAfterV8ContextResult = await callbackExecuteCancelAfterV8ContextCallback . ExecuteAsync ( ) ;
66+ Assert . False ( callbackExecuteCancelAfterV8ContextResult . Success ) ;
67+ Assert . StartsWith ( "Unable to find JavascriptCallback with Id " + callbackExecuteCancelAfterV8ContextCallback . Id , callbackExecuteCancelAfterV8ContextResult . Message ) ;
68+
69+ var callbackExecuteCancelAfterDisposeResponse = await browser . EvaluateScriptAsync ( "(function() { return new Promise(resolve => setTimeout(resolve, 1000)); })" ) ;
70+ Assert . True ( callbackExecuteCancelAfterDisposeResponse . Success ) ;
71+ callbackExecuteCancelAfterDisposeCallback = ( IJavascriptCallback ) callbackExecuteCancelAfterDisposeResponse . Result ;
72+ callbackExecuteCancelAfterDisposeTask = callbackExecuteCancelAfterDisposeCallback . ExecuteAsync ( ) ;
73+ }
74+ Assert . False ( callbackExecuteCancelAfterDisposeCallback . CanExecute ) ;
75+ await Assert . ThrowsAsync < TaskCanceledException > ( ( ) => callbackExecuteCancelAfterDisposeTask ) ;
76+ await Assert . ThrowsAsync < InvalidOperationException > ( ( ) => callbackExecuteCancelAfterDisposeCallback . ExecuteAsync ( ) ) ;
77+ }
78+
79+ [ Fact ]
80+ public async Task ShouldCancelOnCrash ( )
81+ {
82+ AssertInitialLoadComplete ( ) ;
83+
84+ var javascriptResponse = await Browser . EvaluateScriptAsync ( "(function() { return new Promise(resolve => setTimeout(resolve, 1000)); })" ) ;
85+ Assert . True ( javascriptResponse . Success ) ;
86+
87+ var callback = ( IJavascriptCallback ) javascriptResponse . Result ;
88+
89+ var task = callback . ExecuteAsync ( ) ;
90+
91+ await Browser . LoadUrlAsync ( "chrome://crash" ) ;
92+ await Assert . ThrowsAsync < TaskCanceledException > ( ( ) => task ) ;
93+ }
94+
2695 [ Theory ]
2796 [ InlineData ( "(function() { return Promise.resolve(53)})" , 53 ) ]
2897 [ InlineData ( "(function() { return Promise.resolve('53')})" , "53" ) ]
@@ -233,5 +302,23 @@ public async Task ShouldWorkWithExpandoObject()
233302
234303 output . WriteLine ( "Expected {0} : Actual {1}" , expectedDateTime , actualDateTime ) ;
235304 }
305+
306+ [ Fact ]
307+ public async Task ShouldWorkWhenExecutedMultipleTimes ( )
308+ {
309+ AssertInitialLoadComplete ( ) ;
310+
311+ var javascriptResponse = await Browser . EvaluateScriptAsync ( "(function() { return 42; })" ) ;
312+ Assert . True ( javascriptResponse . Success ) ;
313+
314+ var callback = ( IJavascriptCallback ) javascriptResponse . Result ;
315+
316+ for ( var i = 0 ; i < 3 ; i ++ )
317+ {
318+ var callbackResponse = await callback . ExecuteAsync ( ) ;
319+ Assert . True ( callbackResponse . Success ) ;
320+ Assert . Equal ( 42 , callbackResponse . Result ) ;
321+ }
322+ }
236323 }
237324}
0 commit comments