Skip to content

Enhancement - Add EvaluateScriptAsPromiseAsync #3251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 6, 2020

Conversation

amaitland
Copy link
Member

@amaitland amaitland commented Oct 6, 2020

Summary:
Use newly added EvaluateScriptAsPromiseAsync extension method (add using CefSharp;) to evaluate javascript that
returns a promise. Uses Promise.resolve to return the script execution into a promise regardless, EvaluateScriptAsPromiseAsync("return 53") will be turned into a promise.

Differs from other EvaluateScriptAsync methods in that you must return a result.

//This will return 42
await browser.EvaluateScriptAsPromiseAsync("return 42");
//This will return null
await browser.EvaluateScriptAsPromiseAsync("42");

//This will return the content of the AJAX Request
await browser.EvaluateScriptAsPromiseAsync("return (async function() {   const result = await $.ajax({ type: 'GET', url: './robots.txt' });   return result; })();");

//This will return null (missing a return statement in javascript to return the promise generated by the IIFE)
await browser.EvaluateScriptAsPromiseAsync("(async function() {  const result = await $.ajax({ type: 'GET', url: './robots.txt' });   return result; })();");

Changes:

  • Add useImmediatelyInvokedFuncExpression param to EvaluateScriptAsync which wraps the script in an IIFE
    with the cefSharpInternalCallbackId variable defined in scope to allow for deferred completion
  • Wrap script in Immediately Invoked Function Expression and call promise.resolve to guarantee a promise.
  • Return 'CefSharpDefEvalScriptRes' as the result of the js function to defer execution of the callback
  • Call newly added cefSharp.sendEvalScriptResponse method in javascript when promise has been resolved/rejected

This is built up of a few parts and can technically be used by the new user to defer the response until they are ready.
Just return 'CefSharpDefEvalScriptRes' and manually call cefSharp.sendEvalScriptResponse using the cefSharpInternalCallbackId
variable which is injected into the script execution (wrapped in an IIFE to limit scope)

How Has This Been Tested?
Basic unit test has been added.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Updated documentation

Checklist:

  • Tested the code(if applicable)
  • Commented my code
  • Changed the documentation(if applicable)
  • New files have a license disclaimer
  • The formatting is consistent with the project (project supports .editorconfig)

@amaitland amaitland self-assigned this Oct 6, 2020
@amaitland amaitland added this to the 85.3.x milestone Oct 6, 2020
- Add useImmediatelyInvokedFuncExpression param to EvaluateScriptAsync which wraps the script in an IIFE
  with the cefSharpInternalCallbackId variable defined in scope to allow for deferred completion
- Wrap script in Immediately Invoked Function Expression and call promise.resolve to guarantee a promise.
- Return 'CefSharpDefEvalScriptRes' as the result of the js function to defer execution of the callback
- Call newly added cefSharp.sendEvalScriptResponse method in javascript when promise has been resolved/rejected

This is built up of a few parts and can technically be used by the new user to defer the response until they are ready.
Just return `'CefSharpDefEvalScriptRes'` and manually call cefSharp.sendEvalScriptResponse using the cefSharpInternalCallbackId
variable which is injected into the script execution (wrapped in an IIFE to limit scope)
@amaitland amaitland force-pushed the feature/evalpromiseupdated branch from 5233955 to 3aa2c6b Compare October 6, 2020 05:06
@AppVeyorBot
Copy link

@amaitland
Copy link
Member Author

NOTE
If you for some reason return CefSharpDefEvalScriptRes then the c# Task will wait until you manually call cefSharp.sendEvalScriptResponse in javascript.

//Will wait forever unless you call cefSharp.sendEvalScriptResponse yourself
browser.EvaluateScriptAsync("return 'CefSharpDefEvalScriptRes'");
//Will wait forever unless you call cefSharp.sendEvalScriptResponse yourself
browser.EvaluateScriptAsPromiseAsync("return 'CefSharpDefEvalScriptRes'");

@amaitland
Copy link
Member Author

Developing features like this takes considerably time and effort, if you use CefSharp in a commercial application then please consider sponsoring me https://github.com/cefsharp/CefSharp#financial-support

@amaitland amaitland merged commit fd46a4c into cefsharp:master Oct 6, 2020
amaitland added a commit that referenced this pull request Oct 6, 2020
- Add useImmediatelyInvokedFuncExpression param to EvaluateScriptAsync which wraps the script in an IIFE
  with the cefSharpInternalCallbackId variable defined in scope to allow for deferred completion
- Wrap script in Immediately Invoked Function Expression and call promise.resolve to guarantee a promise.
- Return 'CefSharpDefEvalScriptRes' as the result of the js function to defer execution of the callback
- Call newly added cefSharp.sendEvalScriptResponse method in javascript when promise has been resolved/rejected

This is built up of a few parts and can technically be used by the new user to defer the response until they are ready.
Just return `'CefSharpDefEvalScriptRes'` and manually call cefSharp.sendEvalScriptResponse using the cefSharpInternalCallbackId
variable which is injected into the script execution (wrapped in an IIFE to limit scope)
@liudianwei
Copy link

this method do not support object, need basic type

amaitland added a commit that referenced this pull request Oct 19, 2020
amaitland added a commit that referenced this pull request Oct 19, 2020
@amaitland
Copy link
Member Author

I've added an additional test in dadb4fa and objects are working as expected.

EvaluateScriptAsPromiseAsync will support the same objects as EvaluateScriptAsync. Details on EvaluateScriptAsync are listed at https://github.com/cefsharp/CefSharp/wiki/General-Usage#2-how-do-you-call-a-javascript-method-that-returns-a-result

If you are trying to return a HTMLElement then you need to convert it to an object with just the properties you need first (just like if you passed HTMLElement to JSON.stringify())

You are welcome to submit a PR with additional failing test cases.

@amaitland
Copy link
Member Author

#3314 adds the async keywoard to the IIFE used in the generated JavaScript when version 87 is released you will be able to await directly in the returned script no need for an additional IIFE. (Making sure to return the result) e.g.

return await 42;

@amaitland amaitland deleted the feature/evalpromiseupdated branch September 19, 2022 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants