fix: potential async_hooks
crash in NotifyWindowRestore
on Windows (#40576)
* fix: potential async_hooks crash in NotifyWindowRestore on Windows * fix: don't use CallbackScope for Error objects
This commit is contained in:
parent
db2bf1a0d1
commit
8104c7908a
4 changed files with 60 additions and 10 deletions
|
@ -32,13 +32,26 @@ void AutoUpdater::OnError(const std::string& message) {
|
||||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||||
v8::HandleScope handle_scope(isolate);
|
v8::HandleScope handle_scope(isolate);
|
||||||
v8::Local<v8::Object> wrapper;
|
v8::Local<v8::Object> wrapper;
|
||||||
|
|
||||||
|
// We do not use gin::EmitEvent here because we do not want to
|
||||||
|
// put this in its own CallbackScope and delegate to Node.js'
|
||||||
|
// specialized handling for Error objects.
|
||||||
if (GetWrapper(isolate).ToLocal(&wrapper)) {
|
if (GetWrapper(isolate).ToLocal(&wrapper)) {
|
||||||
auto error = v8::Exception::Error(gin::StringToV8(isolate, message));
|
auto error = v8::Exception::Error(gin::StringToV8(isolate, message));
|
||||||
gin_helper::EmitEvent(
|
std::vector<v8::Local<v8::Value>> args = {
|
||||||
isolate, wrapper, "error",
|
gin::StringToV8(isolate, "error"),
|
||||||
error->ToObject(isolate->GetCurrentContext()).ToLocalChecked(),
|
gin::ConvertToV8(
|
||||||
// Message is also emitted to keep compatibility with old code.
|
isolate,
|
||||||
message);
|
error->ToObject(isolate->GetCurrentContext()).ToLocalChecked()),
|
||||||
|
gin::StringToV8(isolate, message),
|
||||||
|
};
|
||||||
|
|
||||||
|
gin_helper::MicrotasksScope microtasks_scope(
|
||||||
|
isolate, wrapper->GetCreationContextChecked()->GetMicrotaskQueue(),
|
||||||
|
true);
|
||||||
|
|
||||||
|
node::MakeCallback(isolate, wrapper, "emit", args.size(), args.data(),
|
||||||
|
{0, 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,14 @@ v8::Local<v8::Value> CallMethodWithArgs(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Object> obj,
|
v8::Local<v8::Object> obj,
|
||||||
const char* method,
|
const char* method,
|
||||||
ValueVector* args) {
|
ValueVector* args) {
|
||||||
|
// Only set up the node::CallbackScope if there's a node environment.
|
||||||
|
std::unique_ptr<node::CallbackScope> callback_scope;
|
||||||
|
if (node::Environment::GetCurrent(isolate)) {
|
||||||
|
v8::HandleScope handle_scope(isolate);
|
||||||
|
callback_scope = std::make_unique<node::CallbackScope>(
|
||||||
|
isolate, v8::Object::New(isolate), node::async_context{0, 0});
|
||||||
|
}
|
||||||
|
|
||||||
// Perform microtask checkpoint after running JavaScript.
|
// Perform microtask checkpoint after running JavaScript.
|
||||||
gin_helper::MicrotasksScope microtasks_scope(
|
gin_helper::MicrotasksScope microtasks_scope(
|
||||||
isolate, obj->GetCreationContextChecked()->GetMicrotaskQueue(), true);
|
isolate, obj->GetCreationContextChecked()->GetMicrotaskQueue(), true);
|
||||||
|
|
|
@ -61,12 +61,10 @@ void InvokeIpcCallback(v8::Local<v8::Context> context,
|
||||||
|
|
||||||
// Only set up the node::CallbackScope if there's a node environment.
|
// Only set up the node::CallbackScope if there's a node environment.
|
||||||
// Sandboxed renderers don't have a node environment.
|
// Sandboxed renderers don't have a node environment.
|
||||||
node::Environment* env = node::Environment::GetCurrent(context);
|
|
||||||
std::unique_ptr<node::CallbackScope> callback_scope;
|
std::unique_ptr<node::CallbackScope> callback_scope;
|
||||||
if (env) {
|
if (node::Environment::GetCurrent(context)) {
|
||||||
node::async_context async_context = {};
|
callback_scope = std::make_unique<node::CallbackScope>(
|
||||||
callback_scope = std::make_unique<node::CallbackScope>(isolate, ipcNative,
|
isolate, ipcNative, node::async_context{0, 0});
|
||||||
async_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto callback_key = gin::ConvertToV8(isolate, callback_name)
|
auto callback_key = gin::ConvertToV8(isolate, callback_name)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { closeWindow, closeAllWindows } from './lib/window-helpers';
|
||||||
import { areColorsSimilar, captureScreen, HexColors, getPixelColor } from './lib/screen-helpers';
|
import { areColorsSimilar, captureScreen, HexColors, getPixelColor } from './lib/screen-helpers';
|
||||||
import { once } from 'node:events';
|
import { once } from 'node:events';
|
||||||
import { setTimeout } from 'node:timers/promises';
|
import { setTimeout } from 'node:timers/promises';
|
||||||
|
import { setTimeout as syncSetTimeout } from 'node:timers';
|
||||||
|
|
||||||
const fixtures = path.resolve(__dirname, 'fixtures');
|
const fixtures = path.resolve(__dirname, 'fixtures');
|
||||||
const mainFixtures = path.resolve(__dirname, 'fixtures');
|
const mainFixtures = path.resolve(__dirname, 'fixtures');
|
||||||
|
@ -1809,6 +1810,36 @@ describe('BrowserWindow module', () => {
|
||||||
expect(w.isFullScreen()).to.equal(true);
|
expect(w.isFullScreen()).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not crash if maximized, minimized, then restored to maximized state', (done) => {
|
||||||
|
w.destroy();
|
||||||
|
w = new BrowserWindow({ show: false });
|
||||||
|
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
w.on('maximize', () => {
|
||||||
|
if (count === 0) syncSetTimeout(() => { w.minimize(); });
|
||||||
|
count++;
|
||||||
|
});
|
||||||
|
|
||||||
|
w.on('minimize', () => {
|
||||||
|
if (count === 1) syncSetTimeout(() => { w.restore(); });
|
||||||
|
count++;
|
||||||
|
});
|
||||||
|
|
||||||
|
w.on('restore', () => {
|
||||||
|
try {
|
||||||
|
throw new Error('hey!');
|
||||||
|
} catch (e: any) {
|
||||||
|
expect(e.message).to.equal('hey!');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
w.maximize();
|
||||||
|
});
|
||||||
|
|
||||||
it('checks normal bounds for maximized transparent window', async () => {
|
it('checks normal bounds for maximized transparent window', async () => {
|
||||||
w.destroy();
|
w.destroy();
|
||||||
w = new BrowserWindow({
|
w = new BrowserWindow({
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue