Skip to main content

从原生到 Electron 中的 JavaScript

· 7 min read

Electron 中用 C++ 或 Objective-C 编写的功能是如何转化为 JavaScript 供终端用户使用的?

🌐 How do Electron's features written in C++ or Objective-C get to JavaScript so they're available to an end-user?


背景

🌐 Background

Electron 是一个 JavaScript 平台,其主要目的是降低开发者构建强大桌面应用的门槛,而无需担心特定平台的实现细节。然而,从本质上讲,Electron 本身仍然需要使用某个系统语言来编写平台特定的功能。

实际上,Electron 会为你处理原生代码,以便你可以专注于单个 JavaScript API。

🌐 In reality, Electron handles the native code for you so that you can focus on a single JavaScript API.

那是如何工作的呢?Electron 中用 C++ 或 Objective-C 编写的功能是如何传递到 JavaScript 中,从而让终端用户可以使用的?

🌐 How does that work, though? How do Electron's features written in C++ or Objective-C get to JavaScript so they're available to an end-user?

要追踪这条路径,让我们从 app 模块 开始。

🌐 To trace this pathway, let's start with the app module.

通过打开我们 lib/ 目录中的 app.ts 文件,你会在顶部附近看到以下这行代码:

🌐 By opening the app.ts file inside our lib/ directory, you'll find the following line of code towards the top:

const binding = process.electronBinding('app');

这一行直接指向 Electron 将其 C++/Objective-C 模块绑定到 JavaScript 供开发者使用的机制。这个函数由 ElectronBindings 类的头文件和实现文件创建。

🌐 This line points directly to Electron's mechanism for binding its C++/Objective-C modules to JavaScript for use by developers. This function is created by the header and implementation file for the ElectronBindings class.

process.electronBinding

这些文件添加了 process.electronBinding 函数,其行为类似于 Node.js 的 process.bindingprocess.binding 是 Node.js require() 方法的底层实现,只不过它允许用户 require 本地代码,而不是其他用 JS 编写的代码。这个自定义的 process.electronBinding 函数赋予了从 Electron 加载本地代码的能力。

🌐 These files add the process.electronBinding function, which behaves like Node.js’ process.binding. process.binding is a lower-level implementation of Node.js' require() method, except it allows users to require native code instead of other code written in JS. This custom process.electronBinding function confers the ability to load native code from Electron.

当顶层 JavaScript 模块(如 app)需要这个本地代码时,该本地代码的状态是如何确定和设置的?方法是如何暴露给 JavaScript 的?属性又是怎样的?

🌐 When a top-level JavaScript module (like app) requires this native code, how is the state of that native code determined and set? Where are the methods exposed up to JavaScript? What about the properties?

native_mate

目前,这个问题的答案可以在 native_mate 中找到:这是 Chromium 的 gin 的一个分支,它使在 C++ 和 JavaScript 之间传递类型更加容易。

🌐 At present, answers to this question can be found in native_mate: a fork of Chromium's gin library that makes it easier to marshal types between C++ and JavaScript.

native_mate/native_mate 中有一个 object_template_builder 的头文件和实现文件。这使我们能够在本地代码中形成模块,其结构符合 JavaScript 开发者的预期。

🌐 Inside native_mate/native_mate there's a header and implementation file for object_template_builder. This is what allow us to form modules in native code whose shape conforms to what JavaScript developers would expect.

mate::ObjectTemplateBuilder

如果我们把每个 Electron 模块都看作一个 object,就更容易理解为什么我们希望使用 object_template_builder 来构建它们。这个类是基于 V8 提供的一个类构建的,V8 是谷歌的开源高性能 JavaScript 和 WebAssembly 引擎,用 C++ 编写。V8 实现了 JavaScript(ECMAScript)规范,因此它的原生功能实现可以直接与 JavaScript 中的实现对应。例如,v8::ObjectTemplate 给我们提供了没有专用构造函数和原型的 JavaScript 对象。它使用 Object[.prototype],在 JavaScript 中等同于 Object.create()

🌐 If we look at every Electron module as an object, it becomes easier to see why we would want to use object_template_builder to construct them. This class is built on top of a class exposed by V8, which is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++. V8 implements the JavaScript (ECMAScript) specification, so its native functionality implementations can be directly correlated to implementations in JavaScript. For example, v8::ObjectTemplate gives us JavaScript objects without a dedicated constructor function and prototype. It uses Object[.prototype], and in JavaScript would be equivalent to Object.create().

要查看其实际效果,请查看应用模块的实现文件 atom_api_app.cc。在底部有如下内容:

🌐 To see this in action, look to the implementation file for the app module, atom_api_app.cc. At the bottom is the following:

mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("getGPUInfo", &App::GetGPUInfo)

在上面这一行中,.SetMethod 被调用在 mate::ObjectTemplateBuilder 上。.SetMethod 可以在 ObjectTemplateBuilder 类的任何实例上被调用,以在 JavaScript 中设置 对象原型 的方法,语法如下:

🌐 In the above line, .SetMethod is called on mate::ObjectTemplateBuilder. .SetMethod can be called on any instance of the ObjectTemplateBuilder class to set methods on the Object prototype in JavaScript, with the following syntax:

.SetMethod("method_name", &function_to_bind)

这是 JavaScript 等效的:

🌐 This is the JavaScript equivalent of:

function App{}
App.prototype.getGPUInfo = function () {
// implementation here
}

此类还包含用于设置模块属性的函数:

🌐 This class also contains functions to set properties on a module:

.SetProperty("property_name", &getter_function_to_bind)

or

.SetProperty("property_name", &getter_function_to_bind, &setter_function_to_bind)

这些将反过来成为 Object.defineProperty 的 JavaScript 实现:

🌐 These would in turn be the JavaScript implementations of Object.defineProperty:

function App {}
Object.defineProperty(App.prototype, 'myProperty', {
get() {
return _myProperty
}
})

and

function App {}
Object.defineProperty(App.prototype, 'myProperty', {
get() {
return _myProperty
}
set(newPropertyValue) {
_myProperty = newPropertyValue
}
})

现在,我们可以按照开发者的期望,创建由原型和属性构成的 JavaScript 对象,并且更清晰地推断在这个较低的系统级别实现的函数和属性!

🌐 It’s possible to create JavaScript objects formed with prototypes and properties as developers expect them, and more clearly reason about functions and properties implemented at this lower system level!

关于在何处实现任何给定模块方法的决定本身就是一个复杂且常常不确定的问题,我们将在以后的文章中讨论。

🌐 The decision around where to implement any given module method is itself a complex and oft-nondeterministic one, which we'll cover in a future post.

Electron 治理

· 4 min read

随着 Electron 在桌面应用中的流行,我们的团队也在不断壮大:我们有更多全职维护者,他们来自不同的公司,生活在不同的时区,并且有不同的兴趣。我们正在引入一个治理结构,以便我们能够平稳地继续发展。

🌐 As Electron grows in popularity for desktop applications, the team working on it has also grown: we have more fulltime maintainers who work for different companies, live in different timezones, and have different interests. We're introducing a governance structure so we can keep growing smoothly.


为什么要改变?

🌐 Why are things changing?

Electron 项目中的人们与来自世界各地的志愿者、全职维护者以及依赖 Electron 的多家公司进行跨时区的协调。到目前为止,我们在非正式的协调方式上取得了成功;但随着团队的增长,我们发现这种方法无法扩展。我们也希望让新贡献者更容易在项目中找到归属感。

🌐 People in the Electron project coordinate in timezones around the world with volunteers, with full-time maintainers, and with several companies who all rely on Electron. Until now, we've been successful with informal coordination; but as the team has grown, we've found that the approach doesn't scale. We also want to make it easier for new contributors to find a place to call home in the project.

工作组

🌐 Working Groups

Electron 的治理包括负责项目不同部分的工作组。我们一开始就有七个工作组:

🌐 Electron governance includes working groups that are responsible for different parts of the project. We're starting out with seven groups:

  • 社区与安全:处理行为准则相关问题。
  • 文档与工具:负责面向外部的工具(例如 FiddleForge)以及 Electron 文档 的管理。
  • 外展:帮助发展 Electron 社区。
  • 发布:确保发布稳定且按计划进行。
  • 安全:执行安全测试并应对安全问题。
  • 升级:整合上游升级,例如 V8、Chromium 和 Node 的新版本。
  • 网站:维护并改进Electron 网站

这些小组将相互协调,但每个小组都有自己的会议时间表和议程,以便各自高效运作。有关这些小组的更多详细信息,请参阅治理仓库

🌐 These groups will coordinate with each other, but each has their own meeting schedules and agendas to be productive on their own. More details on these groups are available at the governance repository.

这会改变 Electron 项目的方向吗?

🌐 Does this change the Electron project's direction?

这不应该对 Electron 的方向产生任何直接影响。如果我们的策略成功,工作小组将使新贡献者更容易找到自己感兴趣的主题,并通过将与他们日常工作无关的讨论转移到其他小组来简化维护者的工作。如果发生这种情况,可能会间接影响事情的发展,因为会有更多不受阻碍的人一起工作。

🌐 This shouldn't have any direct effect on Electron's direction. If our strategy is successful, working groups will make it easier for new contributors to find topics that interest them, and make maintainers' lives simpler by moving discussion unrelated to their day-to-day work to other groups. If that happens, it may indirectly affect things by having more unblocked people working together.

我可以在哪里了解更多信息?

🌐 Where can I learn more?

Chromium FileReader 漏洞修复

· 3 min read

Chrome 中发现了一个高危漏洞,该漏洞会影响所有基于 Chromium 的软件,包括 Electron。

🌐 A High severity vulnerability has been discovered in Chrome which affects all software based on Chromium, including Electron.

此漏洞已被分配编号 CVE-2019-5786。你可以在 Chrome 博客文章 中阅读更多相关信息。

🌐 This vulnerability has been assigned CVE-2019-5786. You can read more about it in the Chrome Blog Post.

请注意,Chrome 已报告此漏洞正在被广泛利用,因此强烈建议你尽快升级 Electron。

🌐 Please note that Chrome has reports of this vulnerability being used in the wild so it is strongly recommended you upgrade Electron ASAP.


范围

🌐 Scope

这会影响任何可能运行第三方或不受信任的 JavaScript 的 Electron 应用。

🌐 This affects any Electron application that may run third-party or untrusted JavaScript.

缓解措施

🌐 Mitigation

受影响的应用应升级到 Electron 的修补版本。

🌐 Affected apps should upgrade to a patched version of Electron.

我们已发布 Electron 的新版本,其中包含针对此漏洞的修复:

🌐 We've published new versions of Electron which include fixes for this vulnerability:

Electron 5 的最新测试版跟踪了 Chromium 73,因此已经修复:

🌐 The latest beta of Electron 5 was tracking Chromium 73 and therefore is already patched:

更多信息

🌐 Further Information

此漏洞由谷歌威胁分析组的Clement Lecigne发现,并报告给了Chrome团队。Chrome博客文章可以在这里找到。

🌐 This vulnerability was discovered by Clement Lecigne of Google's Threat Analysis Group and reported to the Chrome team. The Chrome blog post can be found here.

要了解有关保持你的 Electron 应用安全的最佳做法的更多信息,请参阅我们的[安全教程]。

🌐 To learn more about best practices for keeping your Electron apps secure, see our security tutorial.

如果你希望报告 Electron 中的漏洞,请提交 [GitHub 安全咨询]。

🌐 Please file a GitHub Security Advisory if you wish to report a vulnerability in Electron.

停止对 32 位 Linux 的支持

· 5 min read

Electron 团队将从 Electron v4.0 开始停止对 32 位 Linux(ia32 / i386)的支持。支持基于 32 位 Linux 安装的最后版本是 Electron v3.1,该版本将在 Electron v6 发布之前继续获得支持更新。对 64 位 Linux 和 armv7l 的支持将保持不变。

🌐 The Electron team will discontinue support for 32-bit Linux (ia32 / i386) starting with Electron v4.0. The last version of Electron that supports 32-bit based installations of Linux is Electron v3.1, which will receive support releases until Electron v6 is released. Support for 64-bit based Linux and armv7l will continue unchanged.


Electron 不再支持哪些功能?

🌐 What exactly is Electron no longer supporting?

你可能在电脑上看到过“64位”和“32位”的描述,或者在下载软件时作为选项出现。这个术语用来描述特定的计算机架构。1990年代和2000年代初期生产的大多数电脑都采用基于32位架构的CPU,而之后生产的大多数电脑则基于更新、更强大的64位架构。任天堂64(明白了吗?)和PlayStation 2是首批搭载新架构的广泛可用的消费设备,而2010年之后销售的电脑几乎全部配备了64位处理器。因此,对32位的支持正在减少:Google在2016年3月停止为32位Linux发布Chrome,Canonical在2017年停止提供32位桌面镜像,并在Ubuntu 18.10中彻底放弃对32位的支持。Arch Linux、elementary OS以及其他知名的Linux发行版已经放弃了对这种老旧处理器架构的支持。

🌐 You may have seen the description "64-bit" and "32-bit" as stickers on your computer or as options for downloading software. The term is used to describe a specific computer architecture. Most computers made in the 1990s and early 2000s were made with CPUs that were based on the 32-bit architecture, while most computers made later were based on the newer and more powerful 64-bit architecture. The Nintendo 64 (get it?) and the PlayStation 2 were the first widely available consumer devices with the new architecture, computers sold after 2010 contained almost exclusively 64-bit processors. As a result, support has been shrinking: Google stopped releasing Chrome for 32-bit Linux in March 2016, Canonical stopped providing 32-bit desktop images in 2017 and dropped support for 32-bit altogether with Ubuntu 18.10. Arch Linux, elementary OS, and other prominent Linux distributions have already dropped support for the aging processor architecture.

直到现在,Electron 一直提供并支持可以在较旧的 32 位架构上运行的版本。从 v4.0 版本开始,Electron 团队将不再提供 32 位 Linux 的二进制文件或支持。

🌐 Until now, Electron has provided and supported builds that run on the older 32-bit architecture. From release v4.0 onwards, the Electron team will no longer be able to provide binaries or support for 32-bit Linux.

Electron 一直是一个充满活力的开源项目,我们将继续支持和鼓励有兴趣为各种架构构建 Electron 的开发者。

🌐 Electron has always been a vibrant open source project and we continue to support and encourage developers interested in building Electron for exotic architectures.

这对开发者意味着什么?

🌐 What does that mean for developers?

如果你目前没有为 Linux 提供应用的 32 位发行版,则无需采取任何措施。

🌐 If you are not currently providing 32-bit distributions of your app for Linux, no action is required.

发布 32 位 Linux Electron 应用的项目需要决定下一步怎么做。Electron 3 将支持 32 位 Linux,直到 Electron 6 发布,这为做出决定和制定计划提供了一些时间。

🌐 Projects which ship 32-bit Linux Electron applications will need to decide how to proceed. 32-bit Linux will be supported on Electron 3 until the release of Electron 6, which gives some time to make decisions and plans.

这对用户意味着什么?

🌐 What does that mean for users?

如果你是 Linux 用户,但不确定自己是否在运行 64 位系统,你很可能正在使用 64 位架构。为了确认,你可以在终端中运行 lscpuuname -m 命令,任意一个都会显示你当前的系统架构。

🌐 If you are a Linux user and not sure whether or not you're running a 64-bit based system, you are likely running on a 64-bit based architecture. To make sure, you can run the lscpu or uname -m commands in your terminal. Either one will print your current architecture.

如果你在32位处理器上使用Linux,你很可能已经遇到过很难找到适用于你的操作系统的最新软件的问题。Electron团队与Linux社区的其他知名成员一样,建议你升级到64位架构。

🌐 If you are using Linux on a 32-bit processor, you have likely already encountered difficulties finding recently released software for your operating system. The Electron team joins other prominent members in the Linux community by recommending that you upgrade to a 64-bit based architecture.

BrowserView window.open() 漏洞修复

· 3 min read

发现一个代码漏洞,允许在子窗口中重新启用 Node。

🌐 A code vulnerability has been discovered that allows Node to be re-enabled in child windows.


使用 sandbox: truenativeWindowOpen: true 以及 nodeIntegration: false 打开 BrowserView 会导致 webContents 可以调用 window.open,并且新打开的子窗口将启用 nodeIntegration。此漏洞影响所有受支持的 Electron 版本。

🌐 Opening a BrowserView with sandbox: true or nativeWindowOpen: true and nodeIntegration: false results in a webContents where window.open can be called and the newly opened child window will have nodeIntegration enabled. This vulnerability affects all supported versions of Electron.

缓解措施

🌐 Mitigation

我们已经发布了包含此漏洞修复的新版本 Electron: 2.0.173.0.153.1.34.0.4,以及 5.0.0-beta.2。 我们鼓励所有 Electron 开发者立即将他们的应用更新到最新的稳定版本。

🌐 We've published new versions of Electron which include fixes for this vulnerability: 2.0.17, 3.0.15, 3.1.3, 4.0.4, and 5.0.0-beta.2. We encourage all Electron developers to update their apps to the latest stable version immediately.

如果由于某种原因你无法升级 Electron 版本,你可以通过禁用所有子 Web 内容来缓解此问题:

🌐 If for some reason you are unable to upgrade your Electron version, you can mitigate this issue by disabling all child web contents:

view.webContents.on('-add-new-contents', (e) => e.preventDefault());

更多信息

🌐 Further Information

此漏洞由 PalmerAL 发现,并负责任地报告给了 Electron 项目。

🌐 This vulnerability was found and reported responsibly to the Electron project by PalmerAL.

要了解有关保持你的 Electron 应用安全的最佳做法的更多信息,请参阅我们的[安全教程]。

🌐 To learn more about best practices for keeping your Electron apps secure, see our security tutorial.

如果你希望报告 Electron 中的漏洞,请提交 [GitHub 安全咨询]。

🌐 Please file a GitHub Security Advisory if you wish to report a vulnerability in Electron.

Node.js 本地插件与 Electron 5.0

· 4 min read

如果你在 Electron 5.0 中使用原生 Node.js 插件时遇到问题,则可能需要更新它才能与最新版本的 V8 引擎兼容。

🌐 If you're having trouble using a native Node.js addon with Electron 5.0, there's a chance it needs to be updated to work with the most recent version of V8.


再见 v8::Handle,你好 v8::Local

🌐 Goodbye v8::Handle, Hello v8::Local

2014 年,V8 团队弃用了本地句柄的 v8::Handle,改用 v8::Local。Electron 5.0 包含的 V8 版本最终完全移除了 v8::Handle,仍然使用它的原生 Node.js 插件需要在可以与 Electron 5.0 一起使用之前进行更新。

🌐 In 2014, the V8 team deprecated v8::Handle in favor of v8::Local for local handles. Electron 5.0 includes a version of V8 that has finally removed v8::Handle for good, and native Node.js addons that still use it will need to be updated before they can be used with Electron 5.0.

所需的代码更改很少,但所有仍然使用 v8::Handle 的本地 Node 模块在 Electron 5.0 中都会构建失败,并且需要进行修改。好消息是,Node.js v12 也将包含此 V8 更改,因此任何使用 v8::Handle 的模块无论如何都需要更新,以便在即将发布的 Node 版本中正常工作。

🌐 The required code change is minimal, but every native Node module that still uses v8::Handle will fail to build with Electron 5.0 and will need to be modified. The good news is that Node.js v12 will also include this V8 change, so any modules that use v8::Handle will need to be updated anyway to work with the upcoming version of Node.

我维护一个原生插件,可以帮忙吗?

🌐 I maintain a native addon, how can I help?

如果你维护一个 Node.js 原生插件,确保将所有 v8::Handle 替换为 v8::Local。前者只是后者的一个别名,因此针对这个特定问题不需要做其他更改。

🌐 If you maintain a native addon for Node.js, ensure you replace all occurrences of v8::Handle with v8::Local. The former was just an alias of the latter, so no other changes need to be made to address this specific issue.

你可能也有兴趣了解一下 N-API,它作为 Node.js 本身的一部分独立于 V8 维护,旨在使原生插件免受底层 JavaScript 引擎变化的影响。你可以在 Node.js 网站上的 N-API 文档 中找到更多信息。

🌐 You may also be interested in looking into N-API, which is maintained separately from V8 as a part of Node.js itself, and aims to insulate native addons from changes in the underlying JavaScript engine. You can find more information in the N-API documentation on the Node.js website.

救命!我在应用中使用了原生插件,但它不起作用!

🌐 Help! I use a native addon in my app and it won't work!

如果你在应用中使用 Node.js 的本地插件,而该本地插件由于此问题无法构建,请联系插件作者,看看他们是否发布了修复该问题的新版本。如果没有,联系作者(或提交一个 Pull Request!)可能是你最好的选择。

🌐 If you're consuming a native addon for Node.js in your app and the native addon will not build because of this issue, check with the author of the addon to see if they've released a new version that fixes the problem. If not, reaching out to the author (or opening a Pull Request!) is probably your best bet.

Electron v5.0.0 时间线

· 3 min read

Electron首次激动地公开我们的发布计划,从v5.0.0开始。这是我们迈出的第一步,制定一个公开的长期时间表。

🌐 For the first time ever, Electron is excited to publicize our release schedule starting with v5.0.0. This is our first step in having a public, long-term timeline.


如我们在 v4.0.0 稳定版 博客文章 中提到的那样,我们计划大约每季度发布一次,以保持与 Chromium 发布的更紧密节奏。Chromium 的新版本发布速度非常快——每 6 周一次。

🌐 As mentioned in our v4.0.0 stable release blog post, we are planning to release approximately quarterly to maintain closer cadence with Chromium releases. Chromium releases a new version very quickly -- every 6 weeks.

看看 Electron 与 Chromium 的进展对比情况:

line graph comparing Electron versus Chromium versions

2018年下半年,我们的首要任务是更快地发布,并逐渐赶上Chromium。我们之所以成功,是因为坚持了预定的时间线。Electron 3.0.0 和 4.0.0 在每次发布时的 2-3 个月内发布。我们对继续保持这一速度,期待在5.0.0及以后版本的发布中保持乐观。Electron大约每季度都会有一次大型发行,我们现在正跟上Chromium的发行节奏。抢先于Chromium稳定版发布一直是我们的目标,我们正在朝这个方向迈进。

🌐 In the last half of 2018, our top priority was releasing faster and catching up closer to Chromium. We succeeded by sticking to a predetermined timeline. Electron 3.0.0 and 4.0.0 were released in a 2-3 month timeline for each release. We are optimistic about continuing that pace in releasing 5.0.0 and beyond. With a major Electron release approximately every quarter, we're now keeping pace with Chromium's release cadence. Getting ahead of Chromium stable release is always a goal for us and we are taking steps towards that.

我们很想像 Node.jsChromium 那样承诺未来的日期,但我们尚未达到那个阶段。我们乐观地认为,未来我们将能够制定一个长期的时间表。

🌐 We would love to promise future dates like Node.js and Chromium do, but we are not at that place yet. We are optimistic that we will reach a long-term timeline in the future.

考虑到这一点,我们正在迈出第一步,公开发布 v5.0.0 的发布时间表。你可以在这里查看。

🌐 With that in mind, we are taking first steps by publicly posting our release schedule for v5.0.0. You can find that here.

为了帮助我们测试测试版发布和稳定性,请考虑加入我们的应用反馈计划

🌐 To help us with testing our beta releases and stabilization, please consider joining our App Feedback Program.

Electron 4.0.0

· 13 min read

Electron 团队很高兴地宣布,Electron 4 的稳定版本现已发布!你可以从 electronjs.org 或通过 npm 使用 npm install electron@latest 安装。本次发布包含了大量升级、修复和新功能,我们迫不及待想看到你们用它们创造出什么。查看更多关于此版本的详细信息,并在探索进程中分享你的反馈!

🌐 The Electron team is excited to announce that the stable release of Electron 4 is now available! You can install it from electronjs.org or from npm via npm install electron@latest. The release is packed with upgrades, fixes, and new features, and we can't wait to see what you build with them. Read more for details about this release, and please share any feedback you have as you explore!


有什么新功能?

🌐 What's New?

Electron 的大部分功能由 Chromium、Node.js 和 V8 提供,这些是构成 Electron 的核心组件。因此,Electron 团队的一个关键目标是尽可能跟上这些项目的变化,为开发 Electron 应用的开发者提供访问新的 Web 和 JavaScript 功能的机会。为此,Electron 4 对每个组件都进行了重大版本升级;Electron v4.0.0 包括 Chromium 69.0.3497.106、Node 10.11.0 和 V8 6.9.427.24

🌐 A large part of Electron's functionality is provided by Chromium, Node.js, and V8, the core components that make up Electron. As such, a key goal for the Electron team is to keep up with changes to these projects as much as possible, providing developers who build Electron apps access to new web and JavaScript features. To this end, Electron 4 features major version bumps to each of these components; Electron v4.0.0 includes Chromium 69.0.3497.106, Node 10.11.0, and V8 6.9.427.24.

此外,Electron 4 对 Electron 特定的 API 也进行了更改。你可以在下面找到 Electron 4 主要更改的摘要;有关完整的更改列表,请查看 Electron v4.0.0 发布说明

🌐 In addition, Electron 4 includes changes to Electron-specific APIs. You can find a summary of the major changes in Electron 4 below; for the full list of changes, check out the Electron v4.0.0 release notes.

禁用 remote 模块

🌐 Disabling the remote Module

你现在可以出于安全原因禁用 remote 模块。该模块可以为 BrowserWindowwebview 标签禁用:

🌐 You now have the ability to disable the remote module for security reasons. The module can be disabled for BrowserWindows and for webview tags:

// BrowserWindow
new BrowserWindow({
webPreferences: {
enableRemoteModule: false
}
})

// webview tag
<webview src="http://www.google.com/" enableremotemodule="false"></webview>

有关更多信息,请参阅 BrowserWindow<webview> 标签 文档。

🌐 See the BrowserWindow and <webview> Tag documentation for more information.

过滤 remote.require() / remote.getGlobal() 请求

🌐 Filtering remote.require() / remote.getGlobal() Requests

如果你不想在渲染器进程或 webview 中完全禁用 remote 模块,但希望对哪些模块可以通过 remote.require 引入有更多控制,这个功能会很有用。

🌐 This feature is useful if you don't want to completely disable the remote module in your renderer process or webview but would like additional control over which modules can be required via remote.require.

当在渲染器进程中通过 remote.require 加载模块时,会在 app 模块 上触发一个 remote-require 事件。你可以在事件中(第一个参数)调用 event.preventDefault() 来阻止模块加载。发生 requireWebContents 实例 会作为第二个参数传入,而模块的名称会作为第三个参数传入。相同的事件也会在 WebContents 实例上触发,但在这种情况下,参数只有事件和模块名称。在两种情况下,你都可以通过设置 event.returnValue 的值来返回自定义值。

🌐 When a module is required via remote.require in a renderer process, a remote-require event is raised on the app module. You can call event.preventDefault() on the the event (the first argument) to prevent the module from being loaded. The WebContents instance where the require occurred is passed as the second argument, and the name of the module is passed as the third argument. The same event is also emitted on the WebContents instance, but in this case the only arguments are the event and the module name. In both cases, you can return a custom value by setting the value of event.returnValue.

// Control `remote.require` from all WebContents:
app.on('remote-require', function (event, webContents, requestedModuleName) {
// ...
});

// Control `remote.require` from a specific WebContents instance:
browserWin.webContents.on(
'remote-require',
function (event, requestedModuleName) {
// ...
},
);

以类似的方式,当调用 remote.getGlobal(name) 时,会触发一个 remote-get-global 事件。其工作原理与 remote-require 事件相同:调用 preventDefault() 可以防止返回全局对象,并设置 event.returnValue 来返回自定义值。

🌐 In a similar fashion, when remote.getGlobal(name) is called, a remote-get-global event is raised. This works the same way as the remote-require event: call preventDefault() to prevent the global from being returned, and set event.returnValue to return a custom value.

// Control `remote.getGlobal` from all WebContents:
app.on(
'remote-get-global',
function (event, webContents, requrestedGlobalName) {
// ...
},
);

// Control `remote.getGlobal` from a specific WebContents instance:
browserWin.webContents.on(
'remote-get-global',
function (event, requestedGlobalName) {
// ...
},
);

更多信息,请参阅以下文档:

🌐 For more information, see the following documentation:

JavaScript 访问“关于”面板

🌐 JavaScript Access to the About Panel

在 macOS 上,你现在可以调用 app.showAboutPanel() 来以编程方式显示“关于”面板,就像点击通过 {role: 'about'} 创建的菜单项一样。有关更多信息,请参阅 showAboutPanel 文档

🌐 On macOS, you can now call app.showAboutPanel() to programmatically show the About panel, just like clicking the menu item created via {role: 'about'}. See the showAboutPanel documentation for more information

控制 WebContents 后台节流

🌐 Controlling WebContents Background Throttling

WebContents 实例现在有一个方法 setBackgroundThrottling(allowed),可以在页面处于后台时启用或禁用计时器和动画的节流功能。

let win = new BrowserWindow(...)
win.webContents.setBackgroundThrottling(enableBackgroundThrottling)

请参阅 ‘setBackgroundThrottling’ 文档 以获取更多信息。

🌐 See the setBackgroundThrottling documentation for more information.

重大变化

🌐 Breaking Changes

不再支持 macOS 10.9

🌐 No More macOS 10.9 Support

Chromium 不再支持 macOS 10.9(OS X Mavericks),因此 Electron 4.0 及更高版本也不支持它

🌐 Chromium no longer supports macOS 10.9 (OS X Mavericks), and as a result Electron 4.0 and beyond does not support it either.

单实例锁定

🌐 Single Instance Locking

以前,要将你的应用设置为单实例应用(确保在任何给定时间只运行一个应用实例),你可以使用 app.makeSingleInstance() 方法。从 Electron 4.0 开始,你必须改用 app.requestSingleInstanceLock()。该方法的返回值指示此应用实例是否成功获得锁。如果未能获得锁,你可以假设你的应用的另一个实例已持有锁并且正在运行,然后立即退出。

🌐 Previously, to make your app a Single Instance Application (ensuring that only one instance of your app is running at any given time), you could use the app.makeSingleInstance() method. Starting in Electron 4.0, you must use app.requestSingleInstanceLock() instead. The return value of this method indicates whether or not this instance of your application successfully obtained the lock. If it failed to obtain the lock, you can assume that another instance of your application is already running with the lock and exit immediately.

关于使用 requestSingleInstanceLock() 的示例以及在各种平台上细微行为的信息,请参见 app.requestSingleInstanceLock() 及相关方法的文档second-instance 事件

🌐 For an example of using requestSingleInstanceLock() and information on nuanced behavior on various platforms, see the documentation for app.requestSingleInstanceLock() and related methods and the second-instance event.

win_delay_load_hook

在为 Windows 构建本地模块时,模块的 binding.gyp 中的 win_delay_load_hook 变量必须为 true(这是默认值)。如果没有这个钩子,本地模块将在 Windows 上加载失败,并显示类似 Cannot find module 的错误信息。参见本地模块指南 以获取更多信息。

🌐 When building native modules for windows, the win_delay_load_hook variable in the module's binding.gyp must be true (which is the default). If this hook is not present, then the native module will fail to load on Windows, with an error message like Cannot find module. See the native module guide for more information.

弃用

🌐 Deprecations

以下重大变更计划在 Electron 5.0 中进行,因此在 Electron 4.0 中已弃用。

🌐 The following breaking changes are planned for Electron 5.0, and thus are deprecated in Electron 4.0.

已为 nativeWindowOpen 版 Windows 禁用 Node.js 集成

🌐 Node.js Integration Disabled for nativeWindowOpen-ed Windows

从 Electron 5.0 开始,使用 nativeWindowOpen 选项打开的子窗口将始终禁用 Node.js 集成。

🌐 Starting in Electron 5.0, child windows opened with the nativeWindowOpen option will always have Node.js integration disabled.

webPreferences 默认值

🌐 webPreferences Default Values

在创建新的 BrowserWindow 并设置 webPreferences 选项时,以下 webPreferences 选项的默认值已被弃用,建议使用下面列出的新默认值:

🌐 When creating a new BrowserWindow with the webPreferences option set, the following webPreferences option defaults are deprecated in favor of new defaults listed below:

属性已弃用的默认值新默认值
contextIsolationfalsetrue
nodeIntegrationtruefalse
webviewTag如果设置了 nodeIntegration 则为其值,否则为 truefalse

请注意:目前存在一个已知的错误(#9736),如果 contextIsolation 启用,webview 标签将无法工作。请关注 GitHub 上的该问题以获取最新信息!

🌐 Please note: there is currently a known bug (#9736) that prevents the webview tag from working if contextIsolation is on. Keep an eye on the GitHub issue for up-to-date information!

Electron 安全文档中了解有关上下文隔离、Node 集成以及 webview 标签的更多信息。

🌐 Learn more about context isolation, Node integration, and the webview tag in the Electron security document.

Electron 4.0 仍将使用当前的默认值,但如果你没有为它们传递明确的值,你将看到弃用警告。为了让你的应用为 Electron 5.0 做好准备,请为这些选项使用明确的值。有关每个选项的详细信息,请参见 BrowserWindow 文档

🌐 Electron 4.0 will still use the current defaults, but if you don't pass an explicit value for them, you'll see a deprecation warning. To prepare your app for Electron 5.0, use explicit values for these options. See the BrowserWindow docs for details on each of these options.

webContents.findInPage(text[, options])

medialCapitalAsWordStartwordStart 选项已被弃用,因为它们已在上游移除。

🌐 The medialCapitalAsWordStart and wordStart options have been deprecated as they have been removed upstream.

应用反馈计划

🌐 App Feedback Program

我们在 Electron 3.0 开发进程中建立的应用反馈计划非常成功,因此我们在 4.0 的开发进程中也继续了这一计划。我们想向 Atlassian、Discord、MS Teams、OpenFin、Slack、Symphony、WhatsApp 以及其他参与 4.0 测试版周期的计划成员表示衷心的感谢。要了解更多关于应用反馈计划的信息并参与未来的测试版,请查看我们关于该计划的博客文章

🌐 The App Feedback Program we instituted during the development of Electron 3.0 was successful, so we've continued it during the development of 4.0 as well. We'd like to extend a massive thank you to Atlassian, Discord, MS Teams, OpenFin, Slack, Symphony, WhatsApp, and the other program members for their involvement during the 4.0 beta cycle. To learn more about the App Feedback Program and to participate in future betas, check out our blog post about the program.

下一步计划

🌐 What's Next

在短期内,你可以预期团队将继续专注于跟进构成 Electron 的主要组件的开发,包括 Chromium、Node 和 V8。虽然我们谨慎地不对发布日期作出承诺,但我们的计划是大约每季度随着这些组件的新版本发布 Electron 的新主版本。查看我们的版本说明文档以了解有关 Electron 版本控制的详细信息。

🌐 In the short term, you can expect the team to continue to focus on keeping up with the development of the major components that make up Electron, including Chromium, Node, and V8. Although we are careful not to make promises about release dates, our plan is release new major versions of Electron with new versions of those components approximately quarterly. See our versioning document for more detailed information about versioning in Electron.

有关即将发布的 Electron 版本中计划的重大更改的信息,请参阅我们的计划重大更改文档

🌐 For information on planned breaking changes in upcoming versions of Electron, see our Planned Breaking Changes doc.

SQLite 漏洞修复

· 2 min read

发现了一个远程代码执行漏洞“Magellan”,影响基于 SQLite 或 Chromium 的软件,包括所有版本的 Electron。

🌐 A remote code execution vulnerability, "Magellan," has been discovered affecting software based on SQLite or Chromium, including all versions of Electron.


范围

🌐 Scope

使用 Web SQL 的 Electron 应用会受到影响。

🌐 Electron applications using Web SQL are impacted.

缓解措施

🌐 Mitigation

受影响的应用应停止使用 Web SQL 或升级到 Electron 的修补版本。

🌐 Affected apps should stop using Web SQL or upgrade to a patched version of Electron.

我们已发布 Electron 的新版本,其中包含针对此漏洞的修复:

🌐 We've published new versions of Electron which include fixes for this vulnerability:

在野外没有相关报告;然而,受影响的应用仍被敦促进行缓解。

🌐 There are no reports of this in the wild; however, affected applications are urged to mitigate.

更多信息

🌐 Further Information

该漏洞由腾讯天御团队发现,他们已发布了一篇讨论该漏洞的博客文章

🌐 This vulnerability was discovered by the Tencent Blade team, who have published a blog post that discusses the vulnerability.

要了解有关保持你的 Electron 应用安全的最佳做法的更多信息,请参阅我们的[安全教程]。

🌐 To learn more about best practices for keeping your Electron apps secure, see our security tutorial.

如果你希望报告 Electron 中的漏洞,请提交 [GitHub 安全咨询]。

🌐 Please file a GitHub Security Advisory if you wish to report a vulnerability in Electron.

Electron 应用反馈计划

· 4 min read

Electron 正在努力加快其发布周期并提高稳定性。为了实现这一目标,我们启动了大型 Electron 应用的应用反馈计划,让这些应用测试我们的测试版发布并向我们报告应用特定的问题。这有助于我们优先处理那些可以让应用更快升级到下一个稳定版本的工作。

🌐 Electron is working on making its release cycles faster and more stable. To make that possible, we've started the App Feedback Program for large-scale Electron apps to test our beta releases and report app-specific issues to us. This helps us to prioritize work that will get applications upgraded to our next stable release sooner.

编辑(2020-05-21):该项目已被终止。

🌐 Edit (2020-05-21): This program has been retired.


谁可以加入?

🌐 Who can join?

我们对加入此计划的应用的标准和期望包括以下内容:

🌐 Our criteria and expectations for apps joining this program include the following items:

  • 在 Beta 测试期间,对你的应用进行超过 10,000 小时的用户测试
  • 安排一位专人每周检查,讨论你应用的 Electron 错误和应用拦截器。
  • 你同意遵守 Electron 的行为准则
  • 你愿意分享下一个问题中列出的以下信息

我的 Electron 应用需要共享哪些信息?

🌐 What info does my Electron app have to share?

  • 你的应用在任何 Beta 版本中运行的总用户小时数
  • 你的应用正在测试的 Electron 版本(例如 4.0.0-beta.3)
  • 任何阻止你的应用升级到 Beta 测试版发布线的错误

用户小时数

🌐 User-hours

我们理解并非每个人都能共享确切的用户数量,但更好的数据有助于我们判断某个版本的稳定性。我们要求应用承诺在整个测试周期内进行至少一定数量的用户小时测试,目前要求是 10,000 小时。

🌐 We understand not everyone can share exact user numbers, however better data helps us decide how stable a particular release is. We ask that apps commit to testing a minimum number of user-hours, currently 10,000 across the beta cycle.

  • 10 个用户小时可能是 10 个人测试 1 小时,也可能是 1 个人测试 10 小时
  • 你可以在测试中分配不同的 beta 版本,例如在 3.0.0-beta.2 上测试 5,000 用户小时,然后在 3.0.0-beta.5 上测试 5,000 用户小时。测试越多越好,但我们理解有些应用无法测试每个 beta 版本
  • CI 或 QA 的时间不计入总数;但内部版本会计入总数

为什么我的 Electron 应用应该加入?

🌐 Why should my Electron app join?

你的应用的漏洞将被追踪,并会引起核心 Electron 团队的注意。你的反馈帮助 Electron 团队了解新测试版的运行情况以及需要完成的工作。

🌐 Your app's bugs will be tracked and be on the core Electron team's radar. Your feedback helps the Electron team to see how the new betas are doing and what work needs to be done.

我的申请信息会公开吗?谁可以看到这些信息?

🌐 Will my application's info be shared publicly? Who gets to see this info?

不,你的应用信息不会向公众公开。信息保存在一个私有的 GitHub 仓库中,只有应用反馈计划的成员和 Electron 管理团队 可以查看。所有成员都已同意遵守 Electron 的 行为准则

🌐 No, your application's information will not be shared with the general public. Information is kept in a private GitHub repo that is only viewable to members of the App Feedback Program and Electron Governance. All members have agreed to follow Electron's Code of Conduct.

注册

🌐 Sign up

我们目前仅接受有限数量的注册。如果你有兴趣并且能够满足上述要求,请填写此表格

🌐 We are currently accepting a limited number of signups. If you are interested and are able to fulfill the above requirements, please fill out this form.