mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
16 Commits
v3.0.0-bet
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32ffb0ba17 | ||
|
|
69caea38c1 | ||
|
|
b5bfd9867b | ||
|
|
fb2afe8656 | ||
|
|
c926f3f6dc | ||
|
|
5aa247a627 | ||
|
|
67d202eaf6 | ||
|
|
98033e4f45 | ||
|
|
3d89185396 | ||
|
|
1f430259ce | ||
|
|
ff86cf5f6a | ||
|
|
274a53654c | ||
|
|
8f5fafb636 | ||
|
|
bfbd4a2540 | ||
|
|
07b93d475d | ||
|
|
c9da2d7669 |
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'63.0.3239.150',
|
||||
'libchromiumcontent_revision':
|
||||
'1c542968990da951df27c8a0371a4ab5494a5a6c',
|
||||
'a81166ad79e68fbfe7cf5ba243192d6412e26b37',
|
||||
'node_version':
|
||||
'v9.7.0-33-g538a5023af',
|
||||
'native_mate_revision':
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
version: 1.0.{build}
|
||||
branches:
|
||||
except:
|
||||
- /^release$|^release-\d-\d-x$/
|
||||
build_cloud: electron-16
|
||||
image: electron-16-vs2017
|
||||
environment:
|
||||
DISABLE_CRASH_REPORTER_TESTS: true
|
||||
image: electron-16-vs2017-15.4.5
|
||||
build_script:
|
||||
- ps: >-
|
||||
echo "Build worker image $env:APPVEYOR_BUILD_WORKER_IMAGE"
|
||||
|
||||
&"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
@@ -1891,6 +1891,16 @@ void WebContents::OnGetZoomLevel(content::RenderFrameHost* rfh,
|
||||
rfh->Send(reply_msg);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetPreloadPath(v8::Isolate* isolate) const {
|
||||
if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
|
||||
base::FilePath::StringType preload;
|
||||
if (web_preferences->GetPreloadPath(&preload)) {
|
||||
return mate::ConvertToV8(isolate, preload);
|
||||
}
|
||||
}
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetWebPreferences(v8::Isolate* isolate) {
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
||||
if (!web_preferences)
|
||||
@@ -2053,6 +2063,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setZoomFactor", &WebContents::SetZoomFactor)
|
||||
.SetMethod("_getZoomFactor", &WebContents::GetZoomFactor)
|
||||
.SetMethod("getType", &WebContents::GetType)
|
||||
.SetMethod("_getPreloadPath", &WebContents::GetPreloadPath)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
.SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
|
||||
@@ -232,6 +232,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
const std::vector<std::string>& features,
|
||||
const scoped_refptr<network::ResourceRequestBody>& body);
|
||||
|
||||
// Returns the preload script path of current WebContents.
|
||||
v8::Local<v8::Value> GetPreloadPath(v8::Isolate* isolate) const;
|
||||
|
||||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> GetLastWebPreferences(v8::Isolate* isolate);
|
||||
|
||||
@@ -154,6 +154,14 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
|
||||
|
||||
// Wrap the uv loop with global env.
|
||||
node_bindings_->set_uv_env(env);
|
||||
|
||||
// We already initialized the feature list in
|
||||
// brightray::BrowserMainParts::PreEarlyInitialization(), but
|
||||
// the user JS script would not have had a chance to alter the command-line
|
||||
// switches at that point. Lets reinitialize it here to pick up the
|
||||
// command-line changes.
|
||||
base::FeatureList::ClearInstanceForTesting();
|
||||
brightray::BrowserMainParts::InitializeFeatureList();
|
||||
}
|
||||
|
||||
int AtomBrowserMainParts::PreCreateThreads() {
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,0,0,4
|
||||
PRODUCTVERSION 3,0,0,4
|
||||
FILEVERSION 3,0,0,5
|
||||
PRODUCTVERSION 3,0,0,5
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -109,6 +109,30 @@ void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
|
||||
dict_.MergeDictionary(&extend);
|
||||
}
|
||||
|
||||
bool WebContentsPreferences::GetPreloadPath(
|
||||
base::FilePath::StringType* path) const {
|
||||
DCHECK(path);
|
||||
base::FilePath::StringType preload;
|
||||
if (dict_.GetString(options::kPreloadScript, &preload)) {
|
||||
if (base::FilePath(preload).IsAbsolute()) {
|
||||
*path = std::move(preload);
|
||||
return true;
|
||||
} else {
|
||||
LOG(ERROR) << "preload script must have absolute path.";
|
||||
}
|
||||
} else if (dict_.GetString(options::kPreloadURL, &preload)) {
|
||||
// Translate to file path if there is "preload-url" option.
|
||||
base::FilePath preload_path;
|
||||
if (net::FileURLToFilePath(GURL(preload), &preload_path)) {
|
||||
*path = std::move(preload_path.value());
|
||||
return true;
|
||||
} else {
|
||||
LOG(ERROR) << "preload url must be file:// protocol.";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
content::WebContents* WebContentsPreferences::GetWebContentsFromProcessID(
|
||||
int process_id) {
|
||||
@@ -171,19 +195,8 @@ void WebContentsPreferences::AppendCommandLineSwitches(
|
||||
|
||||
// The preload script.
|
||||
base::FilePath::StringType preload;
|
||||
if (dict_.GetString(options::kPreloadScript, &preload)) {
|
||||
if (base::FilePath(preload).IsAbsolute())
|
||||
command_line->AppendSwitchNative(switches::kPreloadScript, preload);
|
||||
else
|
||||
LOG(ERROR) << "preload script must have absolute path.";
|
||||
} else if (dict_.GetString(options::kPreloadURL, &preload)) {
|
||||
// Translate to file path if there is "preload-url" option.
|
||||
base::FilePath preload_path;
|
||||
if (net::FileURLToFilePath(GURL(preload), &preload_path))
|
||||
command_line->AppendSwitchPath(switches::kPreloadScript, preload_path);
|
||||
else
|
||||
LOG(ERROR) << "preload url must be file:// protocol.";
|
||||
}
|
||||
if (GetPreloadPath(&preload))
|
||||
command_line->AppendSwitchNative(switches::kPreloadScript, preload);
|
||||
|
||||
// Custom args for renderer process
|
||||
base::Value* customArgs;
|
||||
|
||||
@@ -48,6 +48,9 @@ class WebContentsPreferences
|
||||
// Modify the WebPreferences according to preferences.
|
||||
void OverrideWebkitPrefs(content::WebPreferences* prefs);
|
||||
|
||||
// Returns the preload script path.
|
||||
bool GetPreloadPath(base::FilePath::StringType* path) const;
|
||||
|
||||
// Returns the web preferences.
|
||||
base::DictionaryValue* dict() { return &dict_; }
|
||||
const base::DictionaryValue* dict() const { return &dict_; }
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define ATOM_MAJOR_VERSION 3
|
||||
#define ATOM_MINOR_VERSION 0
|
||||
#define ATOM_PATCH_VERSION 0
|
||||
#define ATOM_PRE_RELEASE_VERSION -beta.4
|
||||
#define ATOM_PRE_RELEASE_VERSION -beta.5
|
||||
|
||||
#ifndef ATOM_STRINGIFY
|
||||
#define ATOM_STRINGIFY(n) ATOM_STRINGIFY_HELPER(n)
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "atom/renderer/api/atom_api_renderer_ipc.h"
|
||||
#include "atom/renderer/atom_render_frame_observer.h"
|
||||
#include "base/base_paths.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/path_service.h"
|
||||
#include "chrome/renderer/printing/print_web_view_helper.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
@@ -81,6 +83,12 @@ base::CommandLine::StringVector GetArgv() {
|
||||
return base::CommandLine::ForCurrentProcess()->argv();
|
||||
}
|
||||
|
||||
base::FilePath::StringType GetExecPath() {
|
||||
base::FilePath path;
|
||||
PathService::Get(base::FILE_EXE, &path);
|
||||
return path.value();
|
||||
}
|
||||
|
||||
void InitializeBindings(v8::Local<v8::Object> binding,
|
||||
v8::Local<v8::Context> context) {
|
||||
auto* isolate = context->GetIsolate();
|
||||
@@ -89,6 +97,7 @@ void InitializeBindings(v8::Local<v8::Object> binding,
|
||||
b.SetMethod("crash", AtomBindings::Crash);
|
||||
b.SetMethod("hang", AtomBindings::Hang);
|
||||
b.SetMethod("getArgv", GetArgv);
|
||||
b.SetMethod("getExecPath", GetExecPath);
|
||||
b.SetMethod("getHeapStatistics", &AtomBindings::GetHeapStatistics);
|
||||
b.SetMethod("getProcessMemoryInfo", &AtomBindings::GetProcessMemoryInfo);
|
||||
b.SetMethod("getSystemMemoryInfo", &AtomBindings::GetSystemMemoryInfo);
|
||||
@@ -160,16 +169,12 @@ void AtomSandboxedRendererClient::DidCreateScriptContext(
|
||||
if (!render_frame->IsMainFrame() && !IsDevTools(render_frame))
|
||||
return;
|
||||
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
base::FilePath preload_script_path =
|
||||
command_line->GetSwitchValuePath(switches::kPreloadScript);
|
||||
|
||||
auto* isolate = context->GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
// Wrap the bundle into a function that receives the binding object and the
|
||||
// preload script path as arguments.
|
||||
std::string left = "(function(binding, preloadPath, require) {\n";
|
||||
std::string left = "(function(binding, require) {\n";
|
||||
std::string right = "\n})";
|
||||
// Compile the wrapper and run it to get the function object
|
||||
auto script = v8::Script::Compile(v8::String::Concat(
|
||||
@@ -182,10 +187,10 @@ void AtomSandboxedRendererClient::DidCreateScriptContext(
|
||||
auto binding = v8::Object::New(isolate);
|
||||
InitializeBindings(binding, context);
|
||||
AddRenderBindings(isolate, binding);
|
||||
v8::Local<v8::Value> args[] = {
|
||||
binding, mate::ConvertToV8(isolate, preload_script_path.value())};
|
||||
v8::Local<v8::Value> args[] = {binding};
|
||||
// Execute the function with proper arguments
|
||||
ignore_result(func->Call(context, v8::Null(isolate), 2, args));
|
||||
ignore_result(
|
||||
func->Call(context, v8::Null(isolate), node::arraysize(args), args));
|
||||
}
|
||||
|
||||
void AtomSandboxedRendererClient::WillReleaseScriptContext(
|
||||
|
||||
@@ -268,16 +268,6 @@ void BrowserMainParts::PreMainMessageLoopStart() {
|
||||
}
|
||||
|
||||
void BrowserMainParts::PreMainMessageLoopRun() {
|
||||
// We already initialized the feature list in PreEarlyInitialization(), but
|
||||
// the user JS script would not have had a chance to alter the command-line
|
||||
// switches at that point. Lets force re-initialization here to pick up the
|
||||
// command-line changes. Note that some Chromium code (e.g.
|
||||
// gpu_process_host.cc) queries the feature list between
|
||||
// PreEarlyInitialization() and here so the user script may not have
|
||||
// control over all features. Better than nothing though!
|
||||
base::FeatureList::ClearInstanceForTesting();
|
||||
InitializeFeatureList();
|
||||
|
||||
content::WebUIControllerFactory::RegisterFactory(
|
||||
WebUIControllerFactory::GetInstance());
|
||||
|
||||
|
||||
@@ -43,14 +43,14 @@ class BrowserMainParts : public content::BrowserMainParts {
|
||||
int PreCreateThreads() override;
|
||||
void PostDestroyThreads() override;
|
||||
|
||||
void InitializeFeatureList();
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void InitializeMainNib();
|
||||
void OverrideAppLogsPath();
|
||||
#endif
|
||||
|
||||
void InitializeFeatureList();
|
||||
|
||||
std::unique_ptr<IOThread> io_thread_;
|
||||
|
||||
#if defined(USE_AURA)
|
||||
|
||||
@@ -8,6 +8,19 @@ Electron's `process` object is extended from the
|
||||
[Node.js `process` object](https://nodejs.org/api/process.html).
|
||||
It adds the following events, properties, and methods:
|
||||
|
||||
## Sandbox
|
||||
|
||||
In sandboxed renderers the `process` object contains only a subset of the APIs:
|
||||
- `crash()`
|
||||
- `hang()`
|
||||
- `getHeapStatistics()`
|
||||
- `getProcessMemoryInfo()`
|
||||
- `getSystemMemoryInfo()`
|
||||
- `argv`
|
||||
- `execPath`
|
||||
- `env`
|
||||
- `platform`
|
||||
|
||||
## Events
|
||||
|
||||
### Event: 'loaded'
|
||||
|
||||
@@ -136,7 +136,7 @@ The DPI scale is performed relative to the display containing the DIP point.
|
||||
|
||||
### `screen.screenToDipRect(window, rect)` _Windows_
|
||||
|
||||
* `window` [BrowserWindow](browser-window.md)
|
||||
* `window` [BrowserWindow](browser-window.md) | null
|
||||
* `rect` [Rectangle](structures/rectangle.md)
|
||||
|
||||
Returns [`Rectangle`](structures/rectangle.md)
|
||||
@@ -147,7 +147,7 @@ If `window` is null, scaling will be performed to the display nearest to `rect`.
|
||||
|
||||
### `screen.dipToScreenRect(window, rect)` _Windows_
|
||||
|
||||
* `window` [BrowserWindow](browser-window.md)
|
||||
* `window` [BrowserWindow](browser-window.md) | null
|
||||
* `rect` [Rectangle](structures/rectangle.md)
|
||||
|
||||
Returns [`Rectangle`](structures/rectangle.md)
|
||||
|
||||
@@ -597,7 +597,7 @@ app.on('web-contents-created', (event, contents) => {
|
||||
contents.on('will-navigate', (event, navigationUrl) => {
|
||||
const parsedUrl = new URL(navigationUrl)
|
||||
|
||||
if (url.hostname !== 'my-own-server.com') {
|
||||
if (parsedUrl.hostname !== 'my-own-server.com') {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
@@ -648,5 +648,5 @@ app.on('web-contents-created', (event, contents) => {
|
||||
[browser-view]: ../api/browser-view.md
|
||||
[webview-tag]: ../api/webview-tag.md
|
||||
[web-contents]: ../api/web-contents.md
|
||||
[new-window]: ../api/web-contents#event-new-window
|
||||
[will-navigate]: ../api/web-contents#event-will-navigate
|
||||
[new-window]: ../api/web-contents.md#event-new-window
|
||||
[will-navigate]: ../api/web-contents.md#event-will-navigate
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '3.0.0-beta.4',
|
||||
'version%': '3.0.0-beta.5',
|
||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||
},
|
||||
'includes': [
|
||||
|
||||
@@ -450,7 +450,8 @@ ipcMain.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) {
|
||||
event.returnValue = null
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event, preloadPath) {
|
||||
ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
|
||||
const preloadPath = event.sender._getPreloadPath()
|
||||
let preloadSrc = null
|
||||
let preloadError = null
|
||||
if (preloadPath) {
|
||||
@@ -465,7 +466,6 @@ ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event, preloadPath) {
|
||||
preloadError: preloadError,
|
||||
webContentsId: event.sender.getId(),
|
||||
platform: process.platform,
|
||||
execPath: process.execPath,
|
||||
env: process.env
|
||||
}
|
||||
})
|
||||
|
||||
@@ -67,47 +67,40 @@
|
||||
let nextInode = 0
|
||||
|
||||
const uid = process.getuid != null ? process.getuid() : 0
|
||||
|
||||
const gid = process.getgid != null ? process.getgid() : 0
|
||||
|
||||
const fakeTime = new Date()
|
||||
const msec = (date) => (date || fakeTime).getTime()
|
||||
|
||||
const asarStatsToFsStats = function (stats) {
|
||||
return {
|
||||
dev: 1,
|
||||
ino: ++nextInode,
|
||||
mode: 33188,
|
||||
nlink: 1,
|
||||
uid: uid,
|
||||
gid: gid,
|
||||
rdev: 0,
|
||||
atime: stats.atime || fakeTime,
|
||||
birthtime: stats.birthtime || fakeTime,
|
||||
mtime: stats.mtime || fakeTime,
|
||||
ctime: stats.ctime || fakeTime,
|
||||
size: stats.size,
|
||||
isFile: function () {
|
||||
return stats.isFile
|
||||
},
|
||||
isDirectory: function () {
|
||||
return stats.isDirectory
|
||||
},
|
||||
isSymbolicLink: function () {
|
||||
return stats.isLink
|
||||
},
|
||||
isBlockDevice: function () {
|
||||
return false
|
||||
},
|
||||
isCharacterDevice: function () {
|
||||
return false
|
||||
},
|
||||
isFIFO: function () {
|
||||
return false
|
||||
},
|
||||
isSocket: function () {
|
||||
return false
|
||||
}
|
||||
const {Stats, constants} = require('fs')
|
||||
|
||||
let mode = constants.S_IROTH ^ constants.S_IRGRP ^ constants.S_IRUSR ^ constants.S_IWUSR
|
||||
|
||||
if (stats.isFile) {
|
||||
mode ^= constants.S_IFREG
|
||||
} else if (stats.isDirectory) {
|
||||
mode ^= constants.S_IFDIR
|
||||
} else if (stats.isLink) {
|
||||
mode ^= constants.S_IFLNK
|
||||
}
|
||||
|
||||
return new Stats(
|
||||
1, // dev
|
||||
mode, // mode
|
||||
1, // nlink
|
||||
uid,
|
||||
gid,
|
||||
0, // rdev
|
||||
undefined, // blksize
|
||||
++nextInode, // ino
|
||||
stats.size,
|
||||
undefined, // blocks,
|
||||
msec(stats.atime), // atim_msec
|
||||
msec(stats.mtime), // mtim_msec
|
||||
msec(stats.ctime), // ctim_msec
|
||||
msec(stats.birthtime) // birthtim_msec
|
||||
)
|
||||
}
|
||||
|
||||
// Create a ENOENT error.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
'use strict'
|
||||
|
||||
const {send, sendSync} = binding
|
||||
const {parse} = JSON
|
||||
|
||||
const ipcRenderer = {
|
||||
send (...args) {
|
||||
@@ -11,7 +10,7 @@ const ipcRenderer = {
|
||||
},
|
||||
|
||||
sendSync (...args) {
|
||||
return parse(sendSync('ipc-message-sync', args))
|
||||
return sendSync('ipc-message-sync', args)[0]
|
||||
},
|
||||
|
||||
// No-ops since events aren't received
|
||||
|
||||
@@ -45,7 +45,7 @@ const shouldLogSecurityWarnings = function () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check's if the current window is remote.
|
||||
* Checks if the current window is remote.
|
||||
*
|
||||
* @returns {boolean} - Is this a remote protocol?
|
||||
*/
|
||||
@@ -137,8 +137,8 @@ module.exports = {
|
||||
warnAboutNodeWithRemoteContent: () => {
|
||||
if (getIsRemoteProtocol()) {
|
||||
const warning = `This renderer process has Node.js integration enabled
|
||||
and attempted to load remote content. This exposes users of this app to
|
||||
severe security risks.\n ${moreInformation}`
|
||||
and attempted to load remote content from '${window.location}'. This
|
||||
exposes users of this app to severe security risks.\n ${moreInformation}`
|
||||
|
||||
console.warn('%cElectron Security Warning (Node.js Integration with Remote Content)',
|
||||
'font-weight: bold;', warning)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint no-eval: "off" */
|
||||
/* global binding, preloadPath, Buffer */
|
||||
/* global binding, Buffer */
|
||||
const events = require('events')
|
||||
const electron = require('electron')
|
||||
|
||||
@@ -36,8 +36,8 @@ const loadedModules = new Map([
|
||||
])
|
||||
|
||||
const {
|
||||
preloadSrc, preloadError, webContentsId, platform, execPath, env
|
||||
} = electron.ipcRenderer.sendSync('ELECTRON_BROWSER_SANDBOX_LOAD', preloadPath)
|
||||
preloadSrc, preloadError, webContentsId, platform, env
|
||||
} = electron.ipcRenderer.sendSync('ELECTRON_BROWSER_SANDBOX_LOAD')
|
||||
|
||||
Object.defineProperty(process, 'webContentsId', {
|
||||
configurable: false,
|
||||
@@ -55,9 +55,9 @@ preloadProcess.hang = () => binding.hang()
|
||||
preloadProcess.getHeapStatistics = () => binding.getHeapStatistics()
|
||||
preloadProcess.getProcessMemoryInfo = () => binding.getProcessMemoryInfo()
|
||||
preloadProcess.getSystemMemoryInfo = () => binding.getSystemMemoryInfo()
|
||||
preloadProcess.argv = binding.getArgv()
|
||||
preloadProcess.argv = process.argv = binding.getArgv()
|
||||
preloadProcess.execPath = process.execPath = binding.getExecPath()
|
||||
preloadProcess.platform = process.platform = platform
|
||||
preloadProcess.execPath = process.execPath = execPath
|
||||
preloadProcess.env = process.env = env
|
||||
|
||||
process.on('exit', () => preloadProcess.emit('exit'))
|
||||
|
||||
12
package-lock.json
generated
12
package-lock.json
generated
@@ -4318,6 +4318,12 @@
|
||||
"integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
|
||||
"dev": true
|
||||
},
|
||||
"html-entities": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
|
||||
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
|
||||
"dev": true
|
||||
},
|
||||
"htmlescape": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
|
||||
@@ -6107,6 +6113,12 @@
|
||||
"minimatch": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz",
|
||||
"integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=",
|
||||
"dev": true
|
||||
},
|
||||
"node-version": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/node-version/-/node-version-1.1.3.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.0-beta.5",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -15,13 +15,16 @@
|
||||
"electron-docs-linter": "^2.3.4",
|
||||
"electron-typescript-definitions": "^1.3.5",
|
||||
"github": "^9.2.0",
|
||||
"html-entities": "^1.2.1",
|
||||
"husky": "^0.14.3",
|
||||
"lint": "^1.1.2",
|
||||
"minimist": "^1.2.0",
|
||||
"node-fetch": "^2.1.2",
|
||||
"nugget": "^2.0.1",
|
||||
"remark-cli": "^4.0.0",
|
||||
"remark-preset-lint-markdown-style-guide": "^2.1.1",
|
||||
"request": "^2.68.0",
|
||||
"semver": "^5.5.0",
|
||||
"serve": "^6.5.3",
|
||||
"standard": "^10.0.0",
|
||||
"standard-markdown": "^4.0.0",
|
||||
|
||||
1
script/release-notes/.gitignore
vendored
Normal file
1
script/release-notes/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.cache
|
||||
478
script/release-notes/index.js
Normal file
478
script/release-notes/index.js
Normal file
@@ -0,0 +1,478 @@
|
||||
const { GitProcess } = require('dugite')
|
||||
const Entities = require('html-entities').AllHtmlEntities
|
||||
const fetch = require('node-fetch')
|
||||
const fs = require('fs')
|
||||
const GitHub = require('github')
|
||||
const path = require('path')
|
||||
const semver = require('semver')
|
||||
|
||||
const CACHE_DIR = path.resolve(__dirname, '.cache')
|
||||
// Fill this with tags to ignore if you are generating release notes for older
|
||||
// versions
|
||||
//
|
||||
// E.g. ['v3.0.0-beta.1'] to generate the release notes for 3.0.0-beta.1 :) from
|
||||
// the current 3-0-x branch
|
||||
const EXCLUDE_TAGS = []
|
||||
|
||||
const entities = new Entities()
|
||||
const github = new GitHub()
|
||||
const gitDir = path.resolve(__dirname, '..', '..')
|
||||
github.authenticate({ type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN })
|
||||
let currentBranch
|
||||
|
||||
const semanticMap = new Map()
|
||||
for (const line of fs.readFileSync(path.resolve(__dirname, 'legacy-pr-semantic-map.csv'), 'utf8').split('\n')) {
|
||||
if (!line) continue
|
||||
const bits = line.split(',')
|
||||
if (bits.length !== 2) continue
|
||||
semanticMap.set(bits[0], bits[1])
|
||||
}
|
||||
|
||||
const getCurrentBranch = async () => {
|
||||
if (currentBranch) return currentBranch
|
||||
const gitArgs = ['rev-parse', '--abbrev-ref', 'HEAD']
|
||||
const branchDetails = await GitProcess.exec(gitArgs, gitDir)
|
||||
if (branchDetails.exitCode === 0) {
|
||||
currentBranch = branchDetails.stdout.trim()
|
||||
return currentBranch
|
||||
}
|
||||
throw GitProcess.parseError(branchDetails.stderr)
|
||||
}
|
||||
|
||||
const getBranchOffPoint = async (branchName) => {
|
||||
const gitArgs = ['merge-base', branchName, 'master']
|
||||
const commitDetails = await GitProcess.exec(gitArgs, gitDir)
|
||||
if (commitDetails.exitCode === 0) {
|
||||
return commitDetails.stdout.trim()
|
||||
}
|
||||
throw GitProcess.parseError(commitDetails.stderr)
|
||||
}
|
||||
|
||||
const getTagsOnBranch = async (branchName) => {
|
||||
const gitArgs = ['tag', '--merged', branchName]
|
||||
const tagDetails = await GitProcess.exec(gitArgs, gitDir)
|
||||
if (tagDetails.exitCode === 0) {
|
||||
return tagDetails.stdout.trim().split('\n').filter(tag => !EXCLUDE_TAGS.includes(tag))
|
||||
}
|
||||
throw GitProcess.parseError(tagDetails.stderr)
|
||||
}
|
||||
|
||||
const memLastKnownRelease = new Map()
|
||||
|
||||
const getLastKnownReleaseOnBranch = async (branchName) => {
|
||||
if (memLastKnownRelease.has(branchName)) {
|
||||
return memLastKnownRelease.get(branchName)
|
||||
}
|
||||
const tags = await getTagsOnBranch(branchName)
|
||||
if (!tags.length) {
|
||||
throw new Error(`Branch ${branchName} has no tags, we have no idea what the last release was`)
|
||||
}
|
||||
const branchOffPointTags = await getTagsOnBranch(await getBranchOffPoint(branchName))
|
||||
if (branchOffPointTags.length >= tags.length) {
|
||||
// No release on this branch
|
||||
return null
|
||||
}
|
||||
memLastKnownRelease.set(branchName, tags[tags.length - 1])
|
||||
// Latest tag is the latest release
|
||||
return tags[tags.length - 1]
|
||||
}
|
||||
|
||||
const getBranches = async () => {
|
||||
const gitArgs = ['branch', '--remote']
|
||||
const branchDetails = await GitProcess.exec(gitArgs, gitDir)
|
||||
if (branchDetails.exitCode === 0) {
|
||||
return branchDetails.stdout.trim().split('\n').map(b => b.trim()).filter(branch => branch !== 'origin/HEAD -> origin/master')
|
||||
}
|
||||
throw GitProcess.parseError(branchDetails.stderr)
|
||||
}
|
||||
|
||||
const semverify = (v) => v.replace(/^origin\//, '').replace('x', '0').replace(/-/g, '.')
|
||||
|
||||
const getLastReleaseBranch = async () => {
|
||||
const current = await getCurrentBranch()
|
||||
const allBranches = await getBranches()
|
||||
const releaseBranches = allBranches
|
||||
.filter(branch => /^origin\/[0-9]+-[0-9]+-x$/.test(branch))
|
||||
.filter(branch => branch !== current && branch !== `origin/${current}`)
|
||||
let latest = null
|
||||
for (const b of releaseBranches) {
|
||||
if (latest === null) latest = b
|
||||
if (semver.gt(semverify(b), semverify(latest))) {
|
||||
latest = b
|
||||
}
|
||||
}
|
||||
return latest
|
||||
}
|
||||
|
||||
const commitBeforeTag = async (commit, tag) => {
|
||||
const gitArgs = ['tag', '--contains', commit]
|
||||
const tagDetails = await GitProcess.exec(gitArgs, gitDir)
|
||||
if (tagDetails.exitCode === 0) {
|
||||
return tagDetails.stdout.split('\n').includes(tag)
|
||||
}
|
||||
throw GitProcess.parseError(tagDetails.stderr)
|
||||
}
|
||||
|
||||
const getCommitsMergedIntoCurrentBranchSincePoint = async (point) => {
|
||||
return getCommitsBetween(point, 'HEAD')
|
||||
}
|
||||
|
||||
const getCommitsBetween = async (point1, point2) => {
|
||||
const gitArgs = ['rev-list', `${point1}..${point2}`]
|
||||
const commitsDetails = await GitProcess.exec(gitArgs, gitDir)
|
||||
if (commitsDetails.exitCode !== 0) {
|
||||
throw GitProcess.parseError(commitsDetails.stderr)
|
||||
}
|
||||
return commitsDetails.stdout.trim().split('\n')
|
||||
}
|
||||
|
||||
const TITLE_PREFIX = 'Merged Pull Request: '
|
||||
|
||||
const getCommitDetails = async (commitHash) => {
|
||||
const commitInfo = await (await fetch(`https://github.com/electron/electron/branch_commits/${commitHash}`)).text()
|
||||
const bits = commitInfo.split('</a>)')[0].split('>')
|
||||
const prIdent = bits[bits.length - 1].trim()
|
||||
if (!prIdent || commitInfo.indexOf('href="/electron/electron/pull') === -1) {
|
||||
console.warn(`WARNING: Could not track commit "${commitHash}" to a pull request, it may have been committed directly to the branch`)
|
||||
return null
|
||||
}
|
||||
const title = commitInfo.split('title="')[1].split('"')[0]
|
||||
if (!title.startsWith(TITLE_PREFIX)) {
|
||||
console.warn(`WARNING: Unknown PR title for commit "${commitHash}" in PR "${prIdent}"`)
|
||||
return null
|
||||
}
|
||||
return {
|
||||
mergedFrom: prIdent,
|
||||
prTitle: entities.decode(title.substr(TITLE_PREFIX.length))
|
||||
}
|
||||
}
|
||||
|
||||
const doWork = async (items, fn, concurrent = 5) => {
|
||||
const results = []
|
||||
const toUse = [].concat(items)
|
||||
let i = 1
|
||||
const doBit = async () => {
|
||||
if (toUse.length === 0) return
|
||||
console.log(`Running ${i}/${items.length}`)
|
||||
i += 1
|
||||
|
||||
const item = toUse.pop()
|
||||
const index = toUse.length
|
||||
results[index] = await fn(item)
|
||||
await doBit()
|
||||
}
|
||||
const bits = []
|
||||
for (let i = 0; i < concurrent; i += 1) {
|
||||
bits.push(doBit())
|
||||
}
|
||||
await Promise.all(bits)
|
||||
return results
|
||||
}
|
||||
|
||||
const notes = new Map()
|
||||
|
||||
const NoteType = {
|
||||
FIX: 'fix',
|
||||
FEATURE: 'feature',
|
||||
BREAKING_CHANGE: 'breaking-change',
|
||||
DOCUMENTATION: 'doc',
|
||||
OTHER: 'other',
|
||||
UNKNOWN: 'unknown'
|
||||
}
|
||||
|
||||
class Note {
|
||||
constructor (trueTitle, prNumber, ignoreIfInVersion) {
|
||||
// Self bindings
|
||||
this.guessType = this.guessType.bind(this)
|
||||
this.fetchPrInfo = this.fetchPrInfo.bind(this)
|
||||
this._getPr = this._getPr.bind(this)
|
||||
|
||||
if (!trueTitle.trim()) console.error(prNumber)
|
||||
|
||||
this._ignoreIfInVersion = ignoreIfInVersion
|
||||
this.reverted = false
|
||||
if (notes.has(trueTitle)) {
|
||||
console.warn(`Duplicate PR trueTitle: "${trueTitle}", "${prNumber}" this might cause weird reversions (this would be RARE)`)
|
||||
}
|
||||
|
||||
// Memoize
|
||||
notes.set(trueTitle, this)
|
||||
|
||||
this.originalTitle = trueTitle
|
||||
this.title = trueTitle
|
||||
this.prNumber = prNumber
|
||||
this.stripColon = true
|
||||
if (this.guessType() !== NoteType.UNKNOWN && this.stripColon) {
|
||||
this.title = trueTitle.split(':').slice(1).join(':').trim()
|
||||
}
|
||||
}
|
||||
|
||||
guessType () {
|
||||
if (this.originalTitle.startsWith('fix:') ||
|
||||
this.originalTitle.startsWith('Fix:')) return NoteType.FIX
|
||||
if (this.originalTitle.startsWith('feat:')) return NoteType.FEATURE
|
||||
if (this.originalTitle.startsWith('spec:') ||
|
||||
this.originalTitle.startsWith('build:') ||
|
||||
this.originalTitle.startsWith('test:') ||
|
||||
this.originalTitle.startsWith('chore:') ||
|
||||
this.originalTitle.startsWith('deps:') ||
|
||||
this.originalTitle.startsWith('refactor:') ||
|
||||
this.originalTitle.startsWith('tools:') ||
|
||||
this.originalTitle.startsWith('vendor:') ||
|
||||
this.originalTitle.startsWith('perf:') ||
|
||||
this.originalTitle.startsWith('style:') ||
|
||||
this.originalTitle.startsWith('ci')) return NoteType.OTHER
|
||||
if (this.originalTitle.startsWith('doc:') ||
|
||||
this.originalTitle.startsWith('docs:')) return NoteType.DOCUMENTATION
|
||||
|
||||
this.stripColon = false
|
||||
|
||||
if (this.pr && this.pr.data.labels.find(label => label.name === 'semver/breaking-change')) {
|
||||
return NoteType.BREAKING_CHANGE
|
||||
}
|
||||
// FIXME: Backported features will not be picked up by this
|
||||
if (this.pr && this.pr.data.labels.find(label => label.name === 'semver/nonbreaking-feature')) {
|
||||
return NoteType.FEATURE
|
||||
}
|
||||
|
||||
const n = this.prNumber.replace('#', '')
|
||||
if (semanticMap.has(n)) {
|
||||
switch (semanticMap.get(n)) {
|
||||
case 'feat':
|
||||
return NoteType.FEATURE
|
||||
case 'fix':
|
||||
return NoteType.FIX
|
||||
case 'breaking-change':
|
||||
return NoteType.BREAKING_CHANGE
|
||||
case 'doc':
|
||||
return NoteType.DOCUMENTATION
|
||||
case 'build':
|
||||
case 'vendor':
|
||||
case 'refactor':
|
||||
case 'spec':
|
||||
return NoteType.OTHER
|
||||
default:
|
||||
throw new Error(`Unknown semantic mapping: ${semanticMap.get(n)}`)
|
||||
}
|
||||
}
|
||||
return NoteType.UNKNOWN
|
||||
}
|
||||
|
||||
async _getPr (n) {
|
||||
const cachePath = path.resolve(CACHE_DIR, n)
|
||||
if (fs.existsSync(cachePath)) {
|
||||
return JSON.parse(fs.readFileSync(cachePath, 'utf8'))
|
||||
} else {
|
||||
try {
|
||||
const pr = await github.pullRequests.get({
|
||||
number: n,
|
||||
owner: 'electron',
|
||||
repo: 'electron'
|
||||
})
|
||||
fs.writeFileSync(cachePath, JSON.stringify({ data: pr.data }))
|
||||
return pr
|
||||
} catch (err) {
|
||||
console.info('#### FAILED:', `#${n}`)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fetchPrInfo () {
|
||||
if (this.pr) return
|
||||
const n = this.prNumber.replace('#', '')
|
||||
this.pr = await this._getPr(n)
|
||||
if (this.pr.data.labels.find(label => label.name === `merged/${this._ignoreIfInVersion.replace('origin/', '')}`)) {
|
||||
// This means we probably backported this PR, let's try figure out what
|
||||
// the corresponding backport PR would be by searching through comments
|
||||
// for trop
|
||||
let comments
|
||||
const cacheCommentsPath = path.resolve(CACHE_DIR, `${n}-comments`)
|
||||
if (fs.existsSync(cacheCommentsPath)) {
|
||||
comments = JSON.parse(fs.readFileSync(cacheCommentsPath, 'utf8'))
|
||||
} else {
|
||||
comments = await github.issues.getComments({
|
||||
number: n,
|
||||
owner: 'electron',
|
||||
repo: 'electron',
|
||||
per_page: 100
|
||||
})
|
||||
fs.writeFileSync(cacheCommentsPath, JSON.stringify({ data: comments.data }))
|
||||
}
|
||||
|
||||
const tropComment = comments.data.find(
|
||||
c => (
|
||||
new RegExp(`We have automatically backported this PR to "${this._ignoreIfInVersion.replace('origin/', '')}", please check out #[0-9]+`)
|
||||
).test(c.body)
|
||||
)
|
||||
|
||||
if (tropComment) {
|
||||
const commentBits = tropComment.body.split('#')
|
||||
const tropPrNumber = commentBits[commentBits.length - 1]
|
||||
|
||||
const tropPr = await this._getPr(tropPrNumber)
|
||||
if (tropPr.data.merged && tropPr.data.merge_commit_sha) {
|
||||
if (await commitBeforeTag(tropPr.data.merge_commit_sha, await getLastKnownReleaseOnBranch(this._ignoreIfInVersion))) {
|
||||
this.reverted = true
|
||||
console.log('PR', this.prNumber, 'was backported to a previous version, ignoring from notes')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Note.findByTrueTitle = (trueTitle) => notes.get(trueTitle)
|
||||
|
||||
class ReleaseNotes {
|
||||
constructor (ignoreIfInVersion) {
|
||||
this._ignoreIfInVersion = ignoreIfInVersion
|
||||
this._handledPrs = new Set()
|
||||
this._revertedPrs = new Set()
|
||||
this.other = []
|
||||
this.docs = []
|
||||
this.fixes = []
|
||||
this.features = []
|
||||
this.breakingChanges = []
|
||||
this.unknown = []
|
||||
}
|
||||
|
||||
async parseCommits (commitHashes) {
|
||||
await doWork(commitHashes, async (commit) => {
|
||||
const info = await getCommitDetails(commit)
|
||||
if (!info) return
|
||||
// Only handle each PR once
|
||||
if (this._handledPrs.has(info.mergedFrom)) return
|
||||
this._handledPrs.add(info.mergedFrom)
|
||||
|
||||
// Strip the trop backport prefix
|
||||
const trueTitle = info.prTitle.replace(/^Backport \([0-9]+-[0-9]+-x\) - /, '')
|
||||
if (this._revertedPrs.has(trueTitle)) return
|
||||
|
||||
// Handle PRs that revert other PRs
|
||||
if (trueTitle.startsWith('Revert "')) {
|
||||
const revertedTrueTitle = trueTitle.substr(8, trueTitle.length - 9)
|
||||
this._revertedPrs.add(revertedTrueTitle)
|
||||
const existingNote = Note.findByTrueTitle(revertedTrueTitle)
|
||||
if (existingNote) {
|
||||
existingNote.reverted = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Add a note for this PR
|
||||
const note = new Note(trueTitle, info.mergedFrom, this._ignoreIfInVersion)
|
||||
try {
|
||||
await note.fetchPrInfo()
|
||||
} catch (err) {
|
||||
console.error(commit, info)
|
||||
throw err
|
||||
}
|
||||
switch (note.guessType()) {
|
||||
case NoteType.FIX:
|
||||
this.fixes.push(note)
|
||||
break
|
||||
case NoteType.FEATURE:
|
||||
this.features.push(note)
|
||||
break
|
||||
case NoteType.BREAKING_CHANGE:
|
||||
this.breakingChanges.push(note)
|
||||
break
|
||||
case NoteType.OTHER:
|
||||
this.other.push(note)
|
||||
break
|
||||
case NoteType.DOCUMENTATION:
|
||||
this.docs.push(note)
|
||||
break
|
||||
case NoteType.UNKNOWN:
|
||||
default:
|
||||
this.unknown.push(note)
|
||||
break
|
||||
}
|
||||
}, 20)
|
||||
}
|
||||
|
||||
list (notes) {
|
||||
if (notes.length === 0) {
|
||||
return '_There are no items in this section this release_'
|
||||
}
|
||||
return notes
|
||||
.filter(note => !note.reverted)
|
||||
.sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()))
|
||||
.map((note) => `* ${note.title.trim()} ${note.prNumber}`).join('\n')
|
||||
}
|
||||
|
||||
render () {
|
||||
return `
|
||||
# Release Notes
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
${this.list(this.breakingChanges)}
|
||||
|
||||
## Features
|
||||
|
||||
${this.list(this.features)}
|
||||
|
||||
## Fixes
|
||||
|
||||
${this.list(this.fixes)}
|
||||
|
||||
## Other Changes (E.g. Internal refactors or build system updates)
|
||||
|
||||
${this.list(this.other)}
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
Some documentation updates, fixes and reworks: ${
|
||||
this.docs.length === 0
|
||||
? '_None in this release_'
|
||||
: this.docs.sort((a, b) => a.prNumber.localeCompare(b.prNumber)).map(note => note.prNumber).join(', ')
|
||||
}
|
||||
${this.unknown.filter(n => !n.reverted).length > 0
|
||||
? `## Unknown (fix these before publishing release)
|
||||
|
||||
${this.list(this.unknown)}
|
||||
` : ''}`
|
||||
}
|
||||
}
|
||||
|
||||
async function main () {
|
||||
if (!fs.existsSync(CACHE_DIR)) {
|
||||
fs.mkdirSync(CACHE_DIR)
|
||||
}
|
||||
const lastReleaseBranch = await getLastReleaseBranch()
|
||||
|
||||
const notes = new ReleaseNotes(lastReleaseBranch)
|
||||
const lastKnownReleaseInCurrentStream = await getLastKnownReleaseOnBranch(await getCurrentBranch())
|
||||
const currentBranchOff = await getBranchOffPoint(await getCurrentBranch())
|
||||
|
||||
const commits = await getCommitsMergedIntoCurrentBranchSincePoint(
|
||||
lastKnownReleaseInCurrentStream || currentBranchOff
|
||||
)
|
||||
|
||||
if (!lastKnownReleaseInCurrentStream) {
|
||||
// This means we are the first release in our stream
|
||||
// FIXME: This will not work for minor releases!!!!
|
||||
|
||||
const lastReleaseBranch = await getLastReleaseBranch()
|
||||
const lastBranchOff = await getBranchOffPoint(lastReleaseBranch)
|
||||
commits.push(...await getCommitsBetween(lastBranchOff, currentBranchOff))
|
||||
}
|
||||
|
||||
await notes.parseCommits(commits)
|
||||
|
||||
console.log(notes.render())
|
||||
|
||||
const badNotes = notes.unknown.filter(n => !n.reverted).length
|
||||
if (badNotes > 0) {
|
||||
throw new Error(`You have ${badNotes.length} unknown release notes, please fix them before releasing`)
|
||||
}
|
||||
}
|
||||
|
||||
if (process.mainModule === module) {
|
||||
main().catch((err) => {
|
||||
console.error('Error Occurred:', err)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
193
script/release-notes/legacy-pr-semantic-map.csv
Normal file
193
script/release-notes/legacy-pr-semantic-map.csv
Normal file
@@ -0,0 +1,193 @@
|
||||
12884,fix
|
||||
12093,feat
|
||||
12595,doc
|
||||
12674,doc
|
||||
12577,doc
|
||||
12084,doc
|
||||
12103,doc
|
||||
12948,build
|
||||
12496,feat
|
||||
13133,build
|
||||
12651,build
|
||||
12767,doc
|
||||
12238,build
|
||||
12646,build
|
||||
12373,doc
|
||||
12723,feat
|
||||
12202,doc
|
||||
12504,doc
|
||||
12669,doc
|
||||
13044,feat
|
||||
12746,spec
|
||||
12617,doc
|
||||
12532,feat
|
||||
12619,feat
|
||||
12118,build
|
||||
12921,build
|
||||
13281,doc
|
||||
12059,feat
|
||||
12131,doc
|
||||
12123,doc
|
||||
12080,build
|
||||
12904,fix
|
||||
12562,fix
|
||||
12122,spec
|
||||
12817,spec
|
||||
12254,fix
|
||||
12999,vendor
|
||||
13248,vendor
|
||||
12104,build
|
||||
12477,feat
|
||||
12648,refactor
|
||||
12649,refactor
|
||||
12650,refactor
|
||||
12673,refactor
|
||||
12305,refactor
|
||||
12168,refactor
|
||||
12627,refactor
|
||||
12446,doc
|
||||
12304,refactor
|
||||
12615,breaking-change
|
||||
12135,feat
|
||||
12155,doc
|
||||
12975,fix
|
||||
12501,fix
|
||||
13065,fix
|
||||
13089,build
|
||||
12786,doc
|
||||
12736,doc
|
||||
11966,doc
|
||||
12885,fix
|
||||
12984,refactor
|
||||
12187,build
|
||||
12535,refactor
|
||||
12538,feat
|
||||
12190,fix
|
||||
12139,fix
|
||||
11328,fix
|
||||
12828,feat
|
||||
12614,feat
|
||||
12546,feat
|
||||
12647,refactor
|
||||
12987,build
|
||||
12900,doc
|
||||
12389,doc
|
||||
12387,doc
|
||||
12232,doc
|
||||
12742,build
|
||||
12043,fix
|
||||
12741,fix
|
||||
12995,fix
|
||||
12395,fix
|
||||
12003,build
|
||||
12216,fix
|
||||
12132,fix
|
||||
12062,fix
|
||||
12968,doc
|
||||
12422,doc
|
||||
12149,doc
|
||||
13339,build
|
||||
12044,fix
|
||||
12327,fix
|
||||
12180,fix
|
||||
12263,spec
|
||||
12153,spec
|
||||
13055,feat
|
||||
12113,doc
|
||||
12067,doc
|
||||
12882,build
|
||||
13029,build
|
||||
13067,doc
|
||||
12196,build
|
||||
12797,doc
|
||||
12013,fix
|
||||
12507,fix
|
||||
11607,feat
|
||||
12837,build
|
||||
11613,feat
|
||||
12015,spec
|
||||
12058,doc
|
||||
12403,spec
|
||||
12192,feat
|
||||
12204,doc
|
||||
13294,doc
|
||||
12542,doc
|
||||
12826,refactor
|
||||
12781,doc
|
||||
12157,fix
|
||||
12319,fix
|
||||
12188,build
|
||||
12399,doc
|
||||
12145,doc
|
||||
12661,refactor
|
||||
8953,fix
|
||||
12037,fix
|
||||
12186,spec
|
||||
12397,fix
|
||||
12040,doc
|
||||
12886,refactor
|
||||
12008,refactor
|
||||
12716,refactor
|
||||
12750,refactor
|
||||
12787,refactor
|
||||
12858,refactor
|
||||
12140,refactor
|
||||
12503,refactor
|
||||
12514,refactor
|
||||
12584,refactor
|
||||
12596,refactor
|
||||
12637,refactor
|
||||
12660,refactor
|
||||
12696,refactor
|
||||
12877,refactor
|
||||
13030,refactor
|
||||
12916,build
|
||||
12896,build
|
||||
13039,breaking-change
|
||||
11927,build
|
||||
12847,doc
|
||||
12852,doc
|
||||
12194,fix
|
||||
12870,doc
|
||||
12924,fix
|
||||
12682,doc
|
||||
12004,refactor
|
||||
12601,refactor
|
||||
12998,fix
|
||||
13105,vendor
|
||||
12452,doc
|
||||
12738,fix
|
||||
12536,refactor
|
||||
12189,spec
|
||||
13122,spec
|
||||
12662,fix
|
||||
12665,doc
|
||||
12419,feat
|
||||
12756,doc
|
||||
12616,refactor
|
||||
12679,breaking-change
|
||||
12000,doc
|
||||
12372,build
|
||||
12805,build
|
||||
12348,fix
|
||||
12315,doc
|
||||
12072,doc
|
||||
12912,doc
|
||||
12982,fix
|
||||
12105,doc
|
||||
12917,spec
|
||||
12400,doc
|
||||
12101,feat
|
||||
12642,build
|
||||
13058,fix
|
||||
12913,vendor
|
||||
13298,vendor
|
||||
13042,build
|
||||
11230,feat
|
||||
11459,feat
|
||||
12476,vendor
|
||||
11937,doc
|
||||
12328,build
|
||||
12539,refactor
|
||||
12127,build
|
||||
12537,build
|
||||
|
@@ -1363,6 +1363,8 @@ describe('BrowserWindow module', () => {
|
||||
preload: preload
|
||||
}
|
||||
})
|
||||
ipcRenderer.send('set-web-preferences-on-next-new-window', w.webContents.id, 'preload', preload)
|
||||
|
||||
let htmlPath = path.join(fixtures, 'api', 'sandbox.html?verify-ipc-sender')
|
||||
const pageUrl = 'file://' + htmlPath
|
||||
let childWc
|
||||
@@ -1541,6 +1543,8 @@ describe('BrowserWindow module', () => {
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
ipcRenderer.send('set-web-preferences-on-next-new-window', w.webContents.id, 'preload', preload)
|
||||
|
||||
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?reload-remote-child'))
|
||||
|
||||
ipcMain.on('get-remote-module-path', (event) => {
|
||||
@@ -1565,9 +1569,11 @@ describe('BrowserWindow module', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('validate process.env access in sandbox renderer', (done) => {
|
||||
it('validates process APIs access in sandboxed renderer', (done) => {
|
||||
ipcMain.once('answer', function (event, test) {
|
||||
assert.equal(test, 'foo')
|
||||
assert.equal(test.platform, remote.process.platform)
|
||||
assert.deepEqual(test.env, remote.process.env)
|
||||
assert.equal(test.execPath, remote.process.helperExecPath)
|
||||
done()
|
||||
})
|
||||
remote.process.env.sandboxmain = 'foo'
|
||||
@@ -3072,6 +3078,7 @@ describe('BrowserWindow module', () => {
|
||||
typeofFunctionApply: 'function'
|
||||
},
|
||||
pageContext: {
|
||||
openedLocation: '',
|
||||
preloadProperty: 'undefined',
|
||||
pageProperty: 'string',
|
||||
typeofRequire: 'undefined',
|
||||
|
||||
2
spec/fixtures/api/isolated.html
vendored
2
spec/fixtures/api/isolated.html
vendored
@@ -9,9 +9,11 @@
|
||||
Function.prototype.apply = true
|
||||
|
||||
const opened = window.open()
|
||||
const openedLocation = opened.location
|
||||
opened.close()
|
||||
|
||||
window.postMessage({
|
||||
openedLocation,
|
||||
preloadProperty: typeof window.foo,
|
||||
pageProperty: typeof window.hello,
|
||||
typeofRequire: typeof require,
|
||||
|
||||
6
spec/fixtures/module/preload-sandbox.js
vendored
6
spec/fixtures/module/preload-sandbox.js
vendored
@@ -8,7 +8,11 @@
|
||||
window.test = 'preload'
|
||||
window.process = process
|
||||
if (process.env.sandboxmain) {
|
||||
window.test = process.env.sandboxmain
|
||||
window.test = {
|
||||
env: process.env,
|
||||
execPath: process.execPath,
|
||||
platform: process.platform
|
||||
}
|
||||
}
|
||||
} else if (location.href !== 'about:blank') {
|
||||
addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
@@ -527,6 +527,7 @@ describe('<webview> tag', function () {
|
||||
typeofFunctionApply: 'function'
|
||||
},
|
||||
pageContext: {
|
||||
openedLocation: '',
|
||||
preloadProperty: 'undefined',
|
||||
pageProperty: 'string',
|
||||
typeofRequire: 'undefined',
|
||||
|
||||
2
vendor/libchromiumcontent
vendored
2
vendor/libchromiumcontent
vendored
Submodule vendor/libchromiumcontent updated: c7af30b676...a81166ad79
Reference in New Issue
Block a user