fix: handle electron script errors better (#25328)

This commit is contained in:
Samuel Attard 2020-09-04 14:53:49 -07:00 коммит произвёл GitHub
Родитель 29c1248e96
Коммит 4ad9bcb8b5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 52 добавлений и 16 удалений

Просмотреть файл

@ -10,10 +10,9 @@ config.output = {
filename: path.basename(outPath) filename: path.basename(outPath)
}; };
const { wrapInitWithProfilingTimeout } = config; const { wrapInitWithProfilingTimeout, wrapInitWithTryCatch, ...webpackConfig } = config;
delete config.wrapInitWithProfilingTimeout;
webpack(config, (err, stats) => { webpack(webpackConfig, (err, stats) => {
if (err) { if (err) {
console.error(err); console.error(err);
process.exit(1); process.exit(1);
@ -21,9 +20,17 @@ webpack(config, (err, stats) => {
console.error(stats.toString('normal')); console.error(stats.toString('normal'));
process.exit(1); process.exit(1);
} else { } else {
let contents = fs.readFileSync(outPath, 'utf8');
if (wrapInitWithTryCatch) {
contents = `try {
${contents}
} catch (err) {
console.error('Electron ${webpackConfig.output.filename} script failed to run');
console.error(err);
}`;
}
if (wrapInitWithProfilingTimeout) { if (wrapInitWithProfilingTimeout) {
const contents = fs.readFileSync(outPath, 'utf8'); contents = `function ___electron_webpack_init__() {
const newContents = `function ___electron_webpack_init__() {
${contents} ${contents}
}; };
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) { if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
@ -31,8 +38,8 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
} else { } else {
___electron_webpack_init__(); ___electron_webpack_init__();
}`; }`;
fs.writeFileSync(outPath, newContents);
} }
fs.writeFileSync(outPath, contents);
process.exit(0); process.exit(0);
} }
}); });

Просмотреть файл

@ -69,7 +69,8 @@ module.exports = ({
loadElectronFromAlternateTarget, loadElectronFromAlternateTarget,
targetDeletesNodeGlobals, targetDeletesNodeGlobals,
target, target,
wrapInitWithProfilingTimeout wrapInitWithProfilingTimeout,
wrapInitWithTryCatch
}) => { }) => {
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts'); let entry = path.resolve(electronRoot, 'lib', target, 'init.ts');
if (!fs.existsSync(entry)) { if (!fs.existsSync(entry)) {
@ -87,6 +88,7 @@ module.exports = ({
filename: `${target}.bundle.js` filename: `${target}.bundle.js`
}, },
wrapInitWithProfilingTimeout, wrapInitWithProfilingTimeout,
wrapInitWithTryCatch,
resolve: { resolve: {
alias: { alias: {
'@electron/internal': path.resolve(electronRoot, 'lib'), '@electron/internal': path.resolve(electronRoot, 'lib'),

Просмотреть файл

@ -1,4 +1,5 @@
module.exports = require('./webpack.config.base')({ module.exports = require('./webpack.config.base')({
target: 'isolated_renderer', target: 'isolated_renderer',
alwaysHasNode: false alwaysHasNode: false,
wrapInitWithTryCatch: true
}); });

Просмотреть файл

@ -2,5 +2,6 @@ module.exports = require('./webpack.config.base')({
target: 'renderer', target: 'renderer',
alwaysHasNode: true, alwaysHasNode: true,
targetDeletesNodeGlobals: true, targetDeletesNodeGlobals: true,
wrapInitWithProfilingTimeout: true wrapInitWithProfilingTimeout: true,
wrapInitWithTryCatch: true
}); });

Просмотреть файл

@ -1,5 +1,6 @@
module.exports = require('./webpack.config.base')({ module.exports = require('./webpack.config.base')({
target: 'sandboxed_renderer', target: 'sandboxed_renderer',
alwaysHasNode: false, alwaysHasNode: false,
wrapInitWithProfilingTimeout: true wrapInitWithProfilingTimeout: true,
wrapInitWithTryCatch: true
}); });

Просмотреть файл

@ -2,5 +2,6 @@ module.exports = require('./webpack.config.base')({
target: 'worker', target: 'worker',
loadElectronFromAlternateTarget: 'renderer', loadElectronFromAlternateTarget: 'renderer',
alwaysHasNode: true, alwaysHasNode: true,
targetDeletesNodeGlobals: true targetDeletesNodeGlobals: true,
wrapInitWithTryCatch: true
}); });

Просмотреть файл

@ -400,9 +400,24 @@ node::Environment* NodeBindings::CreateEnvironment(
std::unique_ptr<const char*[]> c_argv = StringVectorToArgArray(args); std::unique_ptr<const char*[]> c_argv = StringVectorToArgArray(args);
isolate_data_ = isolate_data_ =
node::CreateIsolateData(context->GetIsolate(), uv_loop_, platform); node::CreateIsolateData(context->GetIsolate(), uv_loop_, platform);
node::Environment* env = node::CreateEnvironment(
isolate_data_, context, args.size(), c_argv.get(), 0, nullptr); node::Environment* env;
DCHECK(env); if (browser_env_ != BrowserEnvironment::BROWSER) {
v8::TryCatch try_catch(context->GetIsolate());
env = node::CreateEnvironment(isolate_data_, context, args.size(),
c_argv.get(), 0, nullptr);
DCHECK(env);
// This will only be caught when something has gone terrible wrong as all
// electron scripts are wrapped in a try {} catch {} in run-compiler.js
if (try_catch.HasCaught()) {
LOG(ERROR) << "Failed to initialize node environment in process: "
<< process_type;
}
} else {
env = node::CreateEnvironment(isolate_data_, context, args.size(),
c_argv.get(), 0, nullptr);
DCHECK(env);
}
// Clean up the global _noBrowserGlobals that we unironically injected into // Clean up the global _noBrowserGlobals that we unironically injected into
// the global scope // the global scope

Просмотреть файл

@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "shell/common/node_util.h" #include "shell/common/node_util.h"
#include "base/logging.h"
#include "shell/common/node_includes.h" #include "shell/common/node_includes.h"
#include "third_party/electron_node/src/node_native_module_env.h" #include "third_party/electron_node/src/node_native_module_env.h"
@ -17,6 +18,7 @@ v8::MaybeLocal<v8::Value> CompileAndCall(
std::vector<v8::Local<v8::Value>>* arguments, std::vector<v8::Local<v8::Value>>* arguments,
node::Environment* optional_env) { node::Environment* optional_env) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
v8::TryCatch try_catch(isolate);
v8::MaybeLocal<v8::Function> compiled = v8::MaybeLocal<v8::Function> compiled =
node::native_module::NativeModuleEnv::LookupAndCompile( node::native_module::NativeModuleEnv::LookupAndCompile(
context, id, parameters, optional_env); context, id, parameters, optional_env);
@ -24,8 +26,14 @@ v8::MaybeLocal<v8::Value> CompileAndCall(
return v8::MaybeLocal<v8::Value>(); return v8::MaybeLocal<v8::Value>();
} }
v8::Local<v8::Function> fn = compiled.ToLocalChecked().As<v8::Function>(); v8::Local<v8::Function> fn = compiled.ToLocalChecked().As<v8::Function>();
return fn->Call(context, v8::Null(isolate), arguments->size(), v8::MaybeLocal<v8::Value> ret = fn->Call(
arguments->data()); context, v8::Null(isolate), arguments->size(), arguments->data());
// This will only be caught when something has gone terrible wrong as all
// electron scripts are wrapped in a try {} catch {} in run-compiler.js
if (try_catch.HasCaught()) {
LOG(ERROR) << "Failed to CompileAndCall electron script: " << id;
}
return ret;
} }
} // namespace util } // namespace util