Skip to content

Replaced kPromiseCreatorScript with native promise #5094

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

amaitland
Copy link
Member

@amaitland amaitland commented Apr 30, 2025

Summary:

  • Replaced kPromiseCreatorScript with native promise CefV8Value::CreatePromise()

How Has This Been Tested?

  • Existing xUnit tests

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)

Summary by CodeRabbit

  • Refactor
    • Streamlined the creation and handling of JavaScript promises for asynchronous operations, resulting in improved reliability and maintainability.
    • Replaced inline JavaScript evaluation with direct promise creation using the V8 API, reducing potential errors and overhead.
    • Introduced a unified helper method for generating result objects, ensuring consistent response formatting.
  • Chores
    • Removed obsolete constants and redundant error handling related to previous promise creation methods.
  • Tests
    • Added an asynchronous test to validate the structure and properties of asynchronous binding result objects.

Copy link

coderabbitai bot commented Apr 30, 2025

Warning

Rate limit exceeded

@amaitland has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 38 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f7540d2 and 5e55774.

📒 Files selected for processing (2)
  • CefSharp.BrowserSubprocess.Core/BindObjectAsyncHandler.h (3 hunks)
  • CefSharp.Example/Resources/BindingTestAsync.js (1 hunks)

Walkthrough

This update refactors the handling of JavaScript Promises in the asynchronous method and object binding logic. The previous approach, which involved evaluating JavaScript code to create promises and managing separate resolve and reject function pointers, is replaced by direct use of the V8 API to create and resolve/reject Promise objects. Helper methods are introduced for constructing result objects, and redundant script evaluation and error handling are removed. Several class interfaces are updated to reflect these changes, including constructor signatures and static member declarations. A new asynchronous test validates the structure of the result object fields.

Changes

File(s) Change Summary
CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodCallback.cpp,
.../JavascriptAsyncMethodCallback.h
Refactored to use a unified _promise object instead of separate _resolve and _reject pointers. Updated constructor signature to accept a single promise object. Destructor resets _promise instead of both pointers. Logic for success/failure now calls methods on _promise directly.
CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodHandler.cpp Replaced script-based promise creation with direct V8 API call (CefV8Value::CreatePromise()). Updated callback construction to use the promise object. Removed error handling and logging related to script evaluation.
CefSharp.BrowserSubprocess.Core/BindObjectAsyncHandler.h Added static helper method CreateResultObject to construct result objects directly. Replaced JavaScript evaluation-based promise creation and resolution with direct V8 API calls. Updated logic for already bound objects to use the new helper method.
CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.cpp Removed usage of kPromiseCreatorScript. Replaced manual V8 object construction for responses with calls to BindObjectAsyncHandler::CreateResultObject.
CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.h Removed static constant declaration of kPromiseCreatorScript from the public interface.
CefSharp.Example/Resources/BindingTestAsync.js Added a new asynchronous QUnit test to validate that the result object returned by BindObjectAsync contains both lowercase and capitalized keys for count, message, and success. Also tests unbinding of the object.

Sequence Diagram(s)

sequenceDiagram
    participant JS as JavaScript
    participant Handler as AsyncMethodHandler
    participant Callback as JavascriptAsyncMethodCallback
    participant V8 as V8 Engine

    JS->>Handler: Call async method
    Handler->>V8: CreatePromise()
    V8-->>Handler: Promise object
    Handler->>Callback: Construct with promise object
    Handler->>Callback: Register callback
    Handler->>V8: Return promise to JS

    alt On success
        Callback->>V8: ResolvePromise(result)
    else On failure
        Callback->>V8: RejectPromise(exception)
    end
Loading

Poem

In the warren, code once hopped askew,
With scripts for promises, and functions two.
Now a single promise, neat and bright,
Hops through the fields with less to write.
No more tangled scripts to chase,
Just V8 magic, clean and ace!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
CefSharp.BrowserSubprocess.Core/BindObjectAsyncHandler.h (2)

174-176: Minor: keep a local ref to prevent premature GC of the promise

promise is passed to JavascriptAsyncMethodCallback, but retval is also set to it.
While CEF keeps the JavaScript-side alive, keeping an extra CefRefPtr in scope (auto promise = …;) until after SaveMethodCallback can avoid edge-case ref-count churn:

-CefRefPtr<CefV8Value> promise = CefV8Value::CreatePromise();
+auto promise = CefV8Value::CreatePromise();   // keeps ref alive for this scope

Not critical, yet improves clarity.


214-223: Nit: make CreateResultObject inline and accept const String^

Tiny style points:

  1. Marking the helper as inline avoids ODR issues when included in multiple translation units.
  2. The managed string is not modified – pass it as const String^ to express intent.
-static CefRefPtr<CefV8Value> CreateResultObject(int count, String^ message, bool isSuccess)
+inline static CefRefPtr<CefV8Value> CreateResultObject(int count, const String^ message, bool isSuccess)

Purely cosmetic – feel free to ignore if this file is included only once.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5d0cb9 and c4bfd44.

📒 Files selected for processing (6)
  • CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodCallback.cpp (2 hunks)
  • CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodCallback.h (1 hunks)
  • CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodHandler.cpp (1 hunks)
  • CefSharp.BrowserSubprocess.Core/BindObjectAsyncHandler.h (3 hunks)
  • CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.cpp (1 hunks)
  • CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.h (0 hunks)
💤 Files with no reviewable changes (1)
  • CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.h
🔇 Additional comments (9)
CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodCallback.cpp (2)

16-16: Great simplification of promise resolution logic.

Updating the code to check for _promise.get() instead of _resolve.get() and using the promise's native ResolvePromise() method aligns with the PR's goal of using native promise implementation.

Also applies to: 20-20


31-31: Improved promise rejection handling.

Similar to the success case, the code now uses the native RejectPromise() method directly on the promise object rather than executing a separate reject function. This makes the code more concise and maintainable.

Also applies to: 35-35

CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.cpp (2)

659-660: Good refactoring with helper method.

Using BindObjectAsyncHandler::CreateResultObject centralizes the creation of result objects, improving code maintainability and consistency. This replaces manual construction of result objects that was previously done using script evaluation.


663-664: Consistent use of the helper method.

The helper is also correctly used for the case when no objects are bound, ensuring consistent behavior and structure for the response objects regardless of binding success.

CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodCallback.h (3)

19-19: Simplified member variables.

Replacing separate _resolve and _reject members with a single _promise member reduces state management complexity and better represents the unified nature of a promise object.


22-24: Updated constructor for clarity.

The constructor now correctly accepts a single promise object rather than separate resolve and reject functions, reflecting the simplified internal state management.


31-31: Consistent cleanup in destructor.

The destructor now resets the _promise member, maintaining proper cleanup of resources.

CefSharp.BrowserSubprocess.Core/Async/JavascriptAsyncMethodHandler.cpp (2)

27-29: Excellent use of native promise API.

Using CefV8Value::CreatePromise() directly instead of evaluating a JavaScript script is more efficient and eliminates potential evaluation errors. This is the core of the PR's improvement - replacing script-based promise creation with the native API.


30-30: Updated callback creation.

The callback is now correctly created with the promise object, matching the updated constructor signature in JavascriptAsyncMethodCallback. This completes the refactoring of the promise handling flow.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4bfd44 and fc6021e.

📒 Files selected for processing (2)
  • CefSharp.BrowserSubprocess.Core/BindObjectAsyncHandler.h (3 hunks)
  • CefSharp.Example/Resources/BindingTestAsync.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • CefSharp.BrowserSubprocess.Core/BindObjectAsyncHandler.h

@AppVeyorBot
Copy link

@@ -228,23 +191,13 @@ namespace CefSharp
else
{
//Objects already bound or ignore cache
CefRefPtr<CefV8Value> promiseResolve;
CefRefPtr<CefV8Exception> promiseException;
auto promiseResolve = CefV8Value::CreatePromise();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You create a promise and assign it to the result three times. You can create it earlier and assign it to retval, and resolve it later. It will work.
And we can replace exception = "BindObjectAsyncHandler::Execute - Browser wrapper null, unable to bind objects"; with promiseResolve->RejectPromise("BindObjectAsyncHandler::Execute - Browser wrapper null, unable to bind objects");.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants