fix: add microtask runner and fix promise test (#15071)
* fix: Promise resolution and unit test * Update to use microtask runner * Address review
This commit is contained in:
parent
89bf71e580
commit
0c711f690e
13 changed files with 90 additions and 18 deletions
|
@ -1178,7 +1178,7 @@ v8::Local<v8::Promise> App::GetGPUInfo(v8::Isolate* isolate,
|
||||||
|
|
||||||
auto* const info_mgr = GPUInfoManager::GetInstance();
|
auto* const info_mgr = GPUInfoManager::GetInstance();
|
||||||
if (info_type == "complete") {
|
if (info_type == "complete") {
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||||
info_mgr->FetchCompleteInfo(promise);
|
info_mgr->FetchCompleteInfo(promise);
|
||||||
#else
|
#else
|
||||||
info_mgr->FetchBasicInfo(promise);
|
info_mgr->FetchBasicInfo(promise);
|
||||||
|
|
|
@ -26,11 +26,12 @@ GPUInfoManager::~GPUInfoManager() {
|
||||||
|
|
||||||
// Based on
|
// Based on
|
||||||
// https://chromium.googlesource.com/chromium/src.git/+/69.0.3497.106/content/browser/gpu/gpu_data_manager_impl_private.cc#838
|
// https://chromium.googlesource.com/chromium/src.git/+/69.0.3497.106/content/browser/gpu/gpu_data_manager_impl_private.cc#838
|
||||||
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() {
|
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() const {
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_MACOSX)
|
||||||
const auto& gpu_info = gpu_data_manager_->GetGPUInfo();
|
return gpu_data_manager_->GetGPUInfo().gl_vendor.empty();
|
||||||
return (gpu_info.dx_diagnostics.values.empty() &&
|
#elif defined(OS_WIN)
|
||||||
gpu_info.dx_diagnostics.children.empty());
|
return (gpu_data_manager_->GetGPUInfo().dx_diagnostics.values.empty() &&
|
||||||
|
gpu_data_manager_->GetGPUInfo().dx_diagnostics.children.empty());
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,7 +24,7 @@ class GPUInfoManager : public content::GpuDataManagerObserver {
|
||||||
|
|
||||||
GPUInfoManager();
|
GPUInfoManager();
|
||||||
~GPUInfoManager() override;
|
~GPUInfoManager() override;
|
||||||
bool NeedsCompleteGpuInfoCollection();
|
bool NeedsCompleteGpuInfoCollection() const;
|
||||||
void FetchCompleteInfo(scoped_refptr<util::Promise> promise);
|
void FetchCompleteInfo(scoped_refptr<util::Promise> promise);
|
||||||
void FetchBasicInfo(scoped_refptr<util::Promise> promise);
|
void FetchBasicInfo(scoped_refptr<util::Promise> promise);
|
||||||
void OnGpuInfoUpdate() override;
|
void OnGpuInfoUpdate() override;
|
||||||
|
|
|
@ -253,6 +253,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) {
|
bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) {
|
||||||
|
js_env_->OnMessageLoopCreated();
|
||||||
exit_code_ = result_code;
|
exit_code_ = result_code;
|
||||||
return brightray::BrowserMainParts::MainMessageLoopRun(result_code);
|
return brightray::BrowserMainParts::MainMessageLoopRun(result_code);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/browser/microtasks_runner.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/message_loop/message_loop.h"
|
#include "base/message_loop/message_loop.h"
|
||||||
#include "base/task_scheduler/initialization_util.h"
|
#include "base/task_scheduler/initialization_util.h"
|
||||||
|
@ -62,7 +63,15 @@ v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
|
||||||
return isolate;
|
return isolate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JavascriptEnvironment::OnMessageLoopCreated() {
|
||||||
|
DCHECK(!microtasks_runner_);
|
||||||
|
microtasks_runner_.reset(new MicrotasksRunner(isolate()));
|
||||||
|
base::MessageLoopCurrent::Get()->AddTaskObserver(microtasks_runner_.get());
|
||||||
|
}
|
||||||
|
|
||||||
void JavascriptEnvironment::OnMessageLoopDestroying() {
|
void JavascriptEnvironment::OnMessageLoopDestroying() {
|
||||||
|
DCHECK(microtasks_runner_);
|
||||||
|
base::MessageLoopCurrent::Get()->RemoveTaskObserver(microtasks_runner_.get());
|
||||||
platform_->UnregisterIsolate(isolate_);
|
platform_->UnregisterIsolate(isolate_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#ifndef ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
#ifndef ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
||||||
#define ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
#define ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "gin/public/isolate_holder.h"
|
#include "gin/public/isolate_holder.h"
|
||||||
#include "uv.h" // NOLINT(build/include)
|
#include "uv.h" // NOLINT(build/include)
|
||||||
|
@ -16,12 +18,14 @@ class MultiIsolatePlatform;
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
class MicrotasksRunner;
|
||||||
// Manage the V8 isolate and context automatically.
|
// Manage the V8 isolate and context automatically.
|
||||||
class JavascriptEnvironment {
|
class JavascriptEnvironment {
|
||||||
public:
|
public:
|
||||||
explicit JavascriptEnvironment(uv_loop_t* event_loop);
|
explicit JavascriptEnvironment(uv_loop_t* event_loop);
|
||||||
~JavascriptEnvironment();
|
~JavascriptEnvironment();
|
||||||
|
|
||||||
|
void OnMessageLoopCreated();
|
||||||
void OnMessageLoopDestroying();
|
void OnMessageLoopDestroying();
|
||||||
|
|
||||||
node::MultiIsolatePlatform* platform() const { return platform_; }
|
node::MultiIsolatePlatform* platform() const { return platform_; }
|
||||||
|
@ -43,6 +47,8 @@ class JavascriptEnvironment {
|
||||||
v8::Global<v8::Context> context_;
|
v8::Global<v8::Context> context_;
|
||||||
v8::Context::Scope context_scope_;
|
v8::Context::Scope context_scope_;
|
||||||
|
|
||||||
|
std::unique_ptr<MicrotasksRunner> microtasks_runner_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(JavascriptEnvironment);
|
DISALLOW_COPY_AND_ASSIGN(JavascriptEnvironment);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
20
atom/browser/microtasks_runner.cc
Normal file
20
atom/browser/microtasks_runner.cc
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
// Copyright (c) 2018 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/browser/microtasks_runner.h"
|
||||||
|
#include "v8/include/v8.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
MicrotasksRunner::MicrotasksRunner(v8::Isolate* isolate) : isolate_(isolate) {}
|
||||||
|
|
||||||
|
void MicrotasksRunner::WillProcessTask(const base::PendingTask& pending_task) {}
|
||||||
|
|
||||||
|
void MicrotasksRunner::DidProcessTask(const base::PendingTask& pending_task) {
|
||||||
|
v8::Isolate::Scope scope(isolate_);
|
||||||
|
v8::MicrotasksScope::PerformCheckpoint(isolate_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
36
atom/browser/microtasks_runner.h
Normal file
36
atom/browser/microtasks_runner.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright (c) 2018 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||||
|
#define ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||||
|
|
||||||
|
#include "base/message_loop/message_loop.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
class Isolate;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
// Microtasks like promise resolution, are run at the end of the current
|
||||||
|
// task. This class implements a task observer that runs tells v8 to run them.
|
||||||
|
// Microtasks runner implementation is based on the EndOfTaskRunner in blink.
|
||||||
|
// Node follows the kExplicit MicrotasksPolicy, and we do the same in browser
|
||||||
|
// process. Hence, we need to have this task observer to flush the queued
|
||||||
|
// microtasks.
|
||||||
|
class MicrotasksRunner : public base::MessageLoop::TaskObserver {
|
||||||
|
public:
|
||||||
|
explicit MicrotasksRunner(v8::Isolate* isolate);
|
||||||
|
|
||||||
|
// base::MessageLoop::TaskObserver
|
||||||
|
void WillProcessTask(const base::PendingTask& pending_task) override;
|
||||||
|
void DidProcessTask(const base::PendingTask& pending_task) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
v8::Isolate* isolate_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
|
@ -21,8 +21,7 @@ v8::Maybe<bool> Promise::RejectWithErrorMessage(const std::string& string) {
|
||||||
v8::Local<v8::String> error_message =
|
v8::Local<v8::String> error_message =
|
||||||
v8::String::NewFromUtf8(isolate(), string.c_str());
|
v8::String::NewFromUtf8(isolate(), string.c_str());
|
||||||
v8::Local<v8::Value> error = v8::Exception::Error(error_message);
|
v8::Local<v8::Value> error = v8::Exception::Error(error_message);
|
||||||
return GetInner()->Reject(isolate()->GetCurrentContext(),
|
return Reject(error);
|
||||||
mate::ConvertToV8(isolate(), error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Promise> Promise::GetHandle() const {
|
v8::Local<v8::Promise> Promise::GetHandle() const {
|
||||||
|
|
|
@ -32,6 +32,8 @@ class Promise : public base::RefCounted<Promise> {
|
||||||
v8::Undefined(isolate()));
|
v8::Undefined(isolate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Promise resolution is a microtask
|
||||||
|
// We use the MicrotasksRunner to trigger the running of pending microtasks
|
||||||
template <typename T>
|
template <typename T>
|
||||||
v8::Maybe<bool> Resolve(const T& value) {
|
v8::Maybe<bool> Resolve(const T& value) {
|
||||||
return GetInner()->Resolve(isolate()->GetCurrentContext(),
|
return GetInner()->Resolve(isolate()->GetCurrentContext(),
|
||||||
|
|
|
@ -271,6 +271,8 @@ filenames = {
|
||||||
"atom/browser/mac/in_app_purchase_observer.mm",
|
"atom/browser/mac/in_app_purchase_observer.mm",
|
||||||
"atom/browser/mac/in_app_purchase_product.h",
|
"atom/browser/mac/in_app_purchase_product.h",
|
||||||
"atom/browser/mac/in_app_purchase_product.mm",
|
"atom/browser/mac/in_app_purchase_product.mm",
|
||||||
|
"atom/browser/microtasks_runner.cc",
|
||||||
|
"atom/browser/microtasks_runner.h",
|
||||||
"atom/browser/native_browser_view.cc",
|
"atom/browser/native_browser_view.cc",
|
||||||
"atom/browser/native_browser_view.h",
|
"atom/browser/native_browser_view.h",
|
||||||
"atom/browser/native_browser_view_mac.h",
|
"atom/browser/native_browser_view_mac.h",
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
"check-tls": "python ./script/tls.py",
|
"check-tls": "python ./script/tls.py",
|
||||||
"clang-format": "find atom/ brightray/ chromium_src/ -iname *.h -o -iname *.cc -o -iname *.mm | xargs clang-format -i",
|
"clang-format": "find atom/ brightray/ chromium_src/ -iname *.h -o -iname *.cc -o -iname *.mm | xargs clang-format -i",
|
||||||
"lint": "node ./script/lint.js && npm run lint:clang-format && npm run lint:docs",
|
"lint": "node ./script/lint.js && npm run lint:clang-format && npm run lint:docs",
|
||||||
"lint:js": ".node /script/lint.js --js",
|
"lint:js": "node ./script/lint.js --js",
|
||||||
"lint:clang-format": "python script/run-clang-format.py -r -c atom/ chromium_src/ brightray/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
"lint:clang-format": "python script/run-clang-format.py -r -c atom/ chromium_src/ brightray/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
||||||
"lint:cpp": "node ./script/lint.js --cc",
|
"lint:cpp": "node ./script/lint.js --cc",
|
||||||
"lint:py": "node ./script/lint.js --py",
|
"lint:py": "node ./script/lint.js --py",
|
||||||
|
|
|
@ -852,10 +852,9 @@ describe('app module', () => {
|
||||||
await verifyBasicGPUInfo(gpuInfo)
|
await verifyBasicGPUInfo(gpuInfo)
|
||||||
})
|
})
|
||||||
|
|
||||||
// FIXME: this broke with the M69 upgrade.
|
it('succeeds with complete GPUInfo', async () => {
|
||||||
xit('succeeds with complete GPUInfo', async () => {
|
|
||||||
const completeInfo = await getGPUInfo('complete')
|
const completeInfo = await getGPUInfo('complete')
|
||||||
if (process.platform === 'linux' || process.platform === 'darwin') {
|
if (process.platform === 'linux') {
|
||||||
// For linux and macOS complete info is same as basic info
|
// For linux and macOS complete info is same as basic info
|
||||||
await verifyBasicGPUInfo(completeInfo)
|
await verifyBasicGPUInfo(completeInfo)
|
||||||
const basicInfo = await getGPUInfo('basic')
|
const basicInfo = await getGPUInfo('basic')
|
||||||
|
@ -872,11 +871,8 @@ describe('app module', () => {
|
||||||
|
|
||||||
it('fails for invalid info_type', () => {
|
it('fails for invalid info_type', () => {
|
||||||
const invalidType = 'invalid'
|
const invalidType = 'invalid'
|
||||||
const errorMessage =
|
const expectedErrorMessage = "Invalid info type. Use 'basic' or 'complete'"
|
||||||
`app.getGPUInfo() didn't fail for the "${invalidType}" info type`
|
return expect(app.getGPUInfo(invalidType)).to.eventually.be.rejectedWith(expectedErrorMessage)
|
||||||
return app.getGPUInfo(invalidType).then(
|
|
||||||
() => Promise.reject(new Error(errorMessage)),
|
|
||||||
() => Promise.resolve())
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue