Repository: electron/electron (language: cpp)

Issue:
IPC leads to microtasks running too early
### Preflight Checklist

- [x] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [x] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [x] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

34.1.0

### What operating system(s) are you using?

macOS

### Operating System Version

macOS Sequoia 15.3.1

### What arch are you using?

arm64 (including Apple Silicon)

### Last Known Working Electron version

31.0.0

### Expected Behavior

Main process sends IPC communication to render process will not cause event loop logic errors

### Actual Behavior

Main process sends IPC communication to render process will cause event loop logic errors。
here is the example code
```javaScript
// main process
// main.js
click: () => {
  mainWindow.webContents.send('progress', 1)
  Promise.resolve().then((resolve,reject) => {
      console.log('then')
    })
  queueMicrotask(() => {
      console.log('main progress');
    })
  queueMicrotask(() => {
      console.log('main progress2');
    })
  console.log('main complete1')
  mainWindow.webContents.send('complete')
  console.log('main complete2')
},
```
the output in main process is

```javaScript
main complete1
then // microTask
main progress // microTask
main progress2 // microTask
main complete2 
```

In the browser environment, the output is as follows

```javaScript
main complete1
main complete2 
then // microTask
main progress // microTask
main progress2 // microTask
```

### Testcase Gist URL

https://gist.github.com/979220f4c7cac2ba01716ba66fe6f8f6

### Additional Information

_No response_


Discussion / hints:
Let me summarize the desired behavior: `main complete2` should be logged before the micro tasks are run.

Can confirm this is still broken on v36.0.0-beta.6.

v31.3.1 is working fine. It's broken on v31.4.0. Changes: https://github.com/electron/electron/compare/v31.3.1...v31.4.0

The following PRs stand out to me:

- https://github.com/electron/electron/pull/43209 (CC @ckerr)
- https://github.com/electron/electron/pull/43164
- https://github.com/electron/electron/pull/43026
This was indeed triggered by #43209, though the bug theoretically existed before that.

The root cause is that `webContents.send` eventually calls [`Serialize`](https://github.com/electron/electron/blob/32fea719b393c2757c4737386564c910d49b529e/shell/common/v8_util.cc#L37-L40), which has a `gin_helper::MicrotasksScope` that was changed in #43209. That change was one of the few that were unclear what the desired behavior should be and changed.

Fix patch:
diff --git a/shell/common/v8_util.cc b/shell/common/v8_util.cc
index 85ed35cf1ae1f..842e2a1cd36ea 100644
--- a/shell/common/v8_util.cc
+++ b/shell/common/v8_util.cc
@@ -36,7 +36,7 @@ class V8Serializer : public v8::ValueSerializer::Delegate {
 
   bool Serialize(v8::Local<v8::Value> value, blink::CloneableMessage* out) {
     gin_helper::MicrotasksScope microtasks_scope{
-        isolate_->GetCurrentContext(), false,
+        isolate_->GetCurrentContext(), true,
         v8::MicrotasksScope::kDoNotRunMicrotasks};
     WriteBlinkEnvelope(19);
 


Test patch: