mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
20 Commits
v21.0.0-ni
...
v21.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57b863c213 | ||
|
|
52c0a4fafc | ||
|
|
1302ebf50e | ||
|
|
37d93b0482 | ||
|
|
2fd0194e94 | ||
|
|
6d50717eed | ||
|
|
289128b96c | ||
|
|
16db5a112e | ||
|
|
f44ecb7f03 | ||
|
|
8e97f3badf | ||
|
|
a203123473 | ||
|
|
c750936328 | ||
|
|
5f0f517486 | ||
|
|
4ec2de659f | ||
|
|
30d15715a9 | ||
|
|
882fa36940 | ||
|
|
e56f626b94 | ||
|
|
92b0f3e808 | ||
|
|
4f99e3e46c | ||
|
|
f39c1a35e5 |
2
DEPS
2
DEPS
@@ -4,7 +4,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'104.0.5073.0',
|
||||
'node_version':
|
||||
'v16.15.0',
|
||||
'v16.15.1',
|
||||
'nan_version':
|
||||
'16fa32231e2ccd89d2804b3f765319128b20c4ac',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -1 +1 @@
|
||||
21.0.0-nightly.20220603
|
||||
21.0.0-nightly.20220610
|
||||
@@ -16,7 +16,7 @@ win.loadURL('https://twitter.com')
|
||||
|
||||
win.webContents.on(
|
||||
'did-frame-navigate',
|
||||
(event, url, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||
(event, url, httpResponseCode, httpStatusText, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||
const frame = webFrameMain.fromId(frameProcessId, frameRoutingId)
|
||||
if (frame) {
|
||||
const code = 'document.body.innerHTML = document.body.innerHTML.replaceAll("heck", "h*ck")'
|
||||
|
||||
@@ -115,7 +115,7 @@ const win = new BrowserWindow({
|
||||
})
|
||||
```
|
||||
|
||||
On Windows, you can also specify additional parameters. The color of the overlay and its symbols can be specified by setting `titleBarOverlay` to an object and using the `color` and `symbolColor` properties respectively. The height of the overlay can also be specified with the `height` property.
|
||||
On either platform `titleBarOverlay` can also be an object. On both macOS and Windows, the height of the overlay can be specified with the `height` property. On Windows, the color of the overlay and its symbols can be specified using the `color` and `symbolColor` properties respectively.
|
||||
|
||||
If a color option is not specified, the color will default to its system color for the window control buttons. Similarly, if the height option is not specified it will default to the default height:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "21.0.0-nightly.20220603",
|
||||
"version": "21.0.0-nightly.20220610",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -77,7 +77,7 @@
|
||||
"scripts": {
|
||||
"asar": "asar",
|
||||
"generate-version-json": "node script/generate-version-json.js",
|
||||
"lint": "node ./script/lint.js && npm run lint:clang-format && npm run lint:docs",
|
||||
"lint": "node ./script/lint.js && npm run lint:docs",
|
||||
"lint:js": "node ./script/lint.js --js",
|
||||
"lint:clang-format": "python3 script/run-clang-format.py -r -c shell/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
||||
"lint:clang-tidy": "ts-node ./script/run-clang-tidy.ts",
|
||||
@@ -94,6 +94,7 @@
|
||||
"gn-typescript-definitions": "npm run create-typescript-definitions && shx cp electron.d.ts",
|
||||
"pre-flight": "pre-flight",
|
||||
"gn-check": "node ./script/gn-check.js",
|
||||
"gn-format": "python3 script/run-gn-format.py",
|
||||
"precommit": "lint-staged",
|
||||
"preinstall": "node -e 'process.exit(0)'",
|
||||
"prepack": "check-for-leaks",
|
||||
@@ -124,7 +125,7 @@
|
||||
],
|
||||
"*.{gn,gni}": [
|
||||
"npm run gn-check",
|
||||
"python3 script/run-gn-format.py"
|
||||
"npm run gn-format"
|
||||
],
|
||||
"*.py": [
|
||||
"node script/lint.js --py --fix --only --"
|
||||
|
||||
@@ -1799,7 +1799,7 @@ index 0000000000000000000000000000000000000000..d1d6b51e8c0c5bc6a5d09e217eb30483
|
||||
+ args = rebase_path(inputs + outputs, root_build_dir)
|
||||
+}
|
||||
diff --git a/src/node_version.h b/src/node_version.h
|
||||
index 29c9be6366d63be7b340b35cea141e4d7e7f71cc..587735f2ddc0e5d93edd8644d121c6fb31fc4378 100644
|
||||
index 39f6406dd2b52e16a2be5c00c554da30a806ead9..36117c5b36c65f0a8a9bb9c421bc74b82f2b1f3a 100644
|
||||
--- a/src/node_version.h
|
||||
+++ b/src/node_version.h
|
||||
@@ -89,7 +89,10 @@
|
||||
|
||||
@@ -7,7 +7,7 @@ common.gypi is a file that's included in the node header bundle, despite
|
||||
the fact that we do not build node with gyp.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index bdc2c105abeddc4c8e434ead05ebc0d7d82cfae8..3fd1d4ddddc109dfd87f4ba6115948f1c31b1261 100644
|
||||
index 3cfed562577978c41a256fc779f6a3a172e65b3d..96d512630e9727467aa523c2dfc1a4cf9275465b 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -84,6 +84,23 @@
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: fix: add v8_enable_reverse_jsargs defines in common.gypi
|
||||
This can be removed once node upgrades V8 and inevitably has to do this exact same thing. Also hi node people if you are looking at this.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 3fd1d4ddddc109dfd87f4ba6115948f1c31b1261..fd4e0b38eb6ecf81b23186ec663499d1e685fdf8 100644
|
||||
index 96d512630e9727467aa523c2dfc1a4cf9275465b..bdfe81d11cc50f492c93fe48f6946765b6fb5238 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -82,6 +82,8 @@
|
||||
|
||||
@@ -44,7 +44,7 @@ function spawnAndCheckExitCode (cmd, args, opts) {
|
||||
}
|
||||
|
||||
function cpplint (args) {
|
||||
args.unshift(`--project_root=${SOURCE_ROOT}`);
|
||||
args.unshift(`--root=${SOURCE_ROOT}`);
|
||||
const result = childProcess.spawnSync(IS_WINDOWS ? 'cpplint.bat' : 'cpplint.py', args, { encoding: 'utf8', shell: true });
|
||||
// cpplint.py writes EVERYTHING to stderr, including status messages
|
||||
if (result.stderr) {
|
||||
@@ -70,9 +70,9 @@ const LINTERS = [{
|
||||
test: filename => filename.endsWith('.cc') || (filename.endsWith('.h') && !isObjCHeader(filename)),
|
||||
run: (opts, filenames) => {
|
||||
if (opts.fix) {
|
||||
spawnAndCheckExitCode('python', ['script/run-clang-format.py', '--fix', ...filenames]);
|
||||
spawnAndCheckExitCode('python3', ['script/run-clang-format.py', '-r', '--fix', ...filenames]);
|
||||
} else {
|
||||
spawnAndCheckExitCode('python', ['script/run-clang-format.py', ...filenames]);
|
||||
spawnAndCheckExitCode('python3', ['script/run-clang-format.py', '-r', ...filenames]);
|
||||
}
|
||||
cpplint(filenames);
|
||||
}
|
||||
@@ -82,9 +82,9 @@ const LINTERS = [{
|
||||
test: filename => filename.endsWith('.mm') || (filename.endsWith('.h') && isObjCHeader(filename)),
|
||||
run: (opts, filenames) => {
|
||||
if (opts.fix) {
|
||||
spawnAndCheckExitCode('python', ['script/run-clang-format.py', '--fix', ...filenames]);
|
||||
spawnAndCheckExitCode('python3', ['script/run-clang-format.py', '-r', '--fix', ...filenames]);
|
||||
} else {
|
||||
spawnAndCheckExitCode('python', ['script/run-clang-format.py', ...filenames]);
|
||||
spawnAndCheckExitCode('python3', ['script/run-clang-format.py', '-r', ...filenames]);
|
||||
}
|
||||
const filter = [
|
||||
'-readability/braces',
|
||||
|
||||
@@ -18,7 +18,8 @@ const args = require('minimist')(process.argv.slice(2), {
|
||||
});
|
||||
|
||||
async function main () {
|
||||
const nodeDir = path.resolve(BASE, `out/${utils.getOutDir({ shouldLog: true })}/gen/node_headers`);
|
||||
const outDir = utils.getOutDir({ shouldLog: true });
|
||||
const nodeDir = path.resolve(BASE, 'out', outDir, 'gen', 'node_headers');
|
||||
const env = Object.assign({}, process.env, {
|
||||
npm_config_nodedir: nodeDir,
|
||||
npm_config_msvs_version: '2019',
|
||||
@@ -31,6 +32,25 @@ async function main () {
|
||||
const cxx = path.resolve(clangDir, 'clang++');
|
||||
const ld = path.resolve(clangDir, 'lld');
|
||||
|
||||
const platformFlags = [];
|
||||
if (process.platform === 'darwin') {
|
||||
const sdkPath = path.resolve(BASE, 'out', outDir, 'sdk', 'xcode_links');
|
||||
const sdks = (await fs.promises.readdir(sdkPath)).filter(fileName => fileName.endsWith('.sdk'));
|
||||
const sdkToUse = sdks[0];
|
||||
if (!sdkToUse) {
|
||||
console.error('Could not find an SDK to use for the NAN tests');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (sdks.length) {
|
||||
console.warn(`Multiple SDKs found in the xcode_links directory - using ${sdkToUse}`);
|
||||
}
|
||||
|
||||
platformFlags.push(
|
||||
`-isysroot ${path.resolve(sdkPath, sdkToUse)}`
|
||||
);
|
||||
}
|
||||
|
||||
// TODO(ckerr) this is cribbed from read obj/electron/electron_app.ninja.
|
||||
// Maybe it would be better to have this script literally open up that
|
||||
// file and pull cflags_cc from it instead of using bespoke code here?
|
||||
@@ -41,15 +61,17 @@ async function main () {
|
||||
`-isystem"${path.resolve(BASE, 'buildtools', 'third_party', 'libc++')}"`,
|
||||
`-isystem"${path.resolve(BASE, 'buildtools', 'third_party', 'libc++', 'trunk', 'include')}"`,
|
||||
`-isystem"${path.resolve(BASE, 'buildtools', 'third_party', 'libc++abi', 'trunk', 'include')}"`,
|
||||
'-fPIC'
|
||||
'-fPIC',
|
||||
...platformFlags
|
||||
].join(' ');
|
||||
|
||||
const ldflags = [
|
||||
'-stdlib=libc++',
|
||||
'-fuse-ld=lld',
|
||||
`-L"${path.resolve(BASE, 'out', `${utils.getOutDir({ shouldLog: true })}`, 'obj', 'buildtools', 'third_party', 'libc++abi')}"`,
|
||||
`-L"${path.resolve(BASE, 'out', `${utils.getOutDir({ shouldLog: true })}`, 'obj', 'buildtools', 'third_party', 'libc++')}"`,
|
||||
'-lc++abi'
|
||||
`-L"${path.resolve(BASE, 'out', outDir, 'obj', 'buildtools', 'third_party', 'libc++abi')}"`,
|
||||
`-L"${path.resolve(BASE, 'out', outDir, 'obj', 'buildtools', 'third_party', 'libc++')}"`,
|
||||
'-lc++abi',
|
||||
...platformFlags
|
||||
].join(' ');
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
@@ -66,6 +88,7 @@ async function main () {
|
||||
cwd: NAN_DIR,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
if (buildStatus !== 0) {
|
||||
console.error('Failed to build nan test modules');
|
||||
return process.exit(buildStatus);
|
||||
|
||||
@@ -147,7 +147,7 @@ const getPreviousPoint = async (point) => {
|
||||
}
|
||||
};
|
||||
|
||||
async function getReleaseNotes (range, newVersion) {
|
||||
async function getReleaseNotes (range, newVersion, unique) {
|
||||
const rangeList = range.split('..') || ['HEAD'];
|
||||
const to = rangeList.pop();
|
||||
const from = rangeList.pop() || (await getPreviousPoint(to));
|
||||
@@ -158,7 +158,7 @@ async function getReleaseNotes (range, newVersion) {
|
||||
|
||||
const notes = await notesGenerator.get(from, to, newVersion);
|
||||
const ret = {
|
||||
text: notesGenerator.render(notes)
|
||||
text: notesGenerator.render(notes, unique)
|
||||
};
|
||||
|
||||
if (notes.unknown.length) {
|
||||
@@ -170,7 +170,7 @@ async function getReleaseNotes (range, newVersion) {
|
||||
|
||||
async function main () {
|
||||
const opts = minimist(process.argv.slice(2), {
|
||||
boolean: ['help'],
|
||||
boolean: ['help', 'unique'],
|
||||
string: ['version']
|
||||
});
|
||||
opts.range = opts._.shift();
|
||||
@@ -179,13 +179,14 @@ async function main () {
|
||||
console.log(`
|
||||
easy usage: ${name} version
|
||||
|
||||
full usage: ${name} [begin..]end [--version version]
|
||||
full usage: ${name} [begin..]end [--version version] [--unique]
|
||||
|
||||
* 'begin' and 'end' are two git references -- tags, branches, etc --
|
||||
from which the release notes are generated.
|
||||
* if omitted, 'begin' defaults to the previous tag in end's branch.
|
||||
* if omitted, 'version' defaults to 'end'. Specifying a version is
|
||||
useful if you're making notes on a new version that isn't tagged yet.
|
||||
* '--unique' omits changes that also landed in other branches.
|
||||
|
||||
For example, these invocations are equivalent:
|
||||
${process.argv[1]} v4.0.1
|
||||
@@ -194,7 +195,7 @@ For example, these invocations are equivalent:
|
||||
return 0;
|
||||
}
|
||||
|
||||
const notes = await getReleaseNotes(opts.range, opts.version);
|
||||
const notes = await getReleaseNotes(opts.range, opts.version, opts.unique);
|
||||
console.log(notes.text);
|
||||
if (notes.warning) {
|
||||
throw new Error(notes.warning);
|
||||
|
||||
@@ -596,10 +596,14 @@ function renderDescription (commit) {
|
||||
const renderNote = (commit, excludeBranch) =>
|
||||
`* ${renderDescription(commit)} ${renderLink(commit)} ${renderTrops(commit, excludeBranch)}\n`;
|
||||
|
||||
const renderNotes = (notes) => {
|
||||
const renderNotes = (notes, unique = false) => {
|
||||
const rendered = [`# Release Notes for ${notes.name}\n\n`];
|
||||
|
||||
const renderSection = (title, commits) => {
|
||||
const renderSection = (title, commits, unique) => {
|
||||
if (unique) {
|
||||
// omit changes that also landed in other branches
|
||||
commits = commits.filter((commit) => renderTrops(commit, notes.toBranch).length === 0);
|
||||
}
|
||||
if (commits.length > 0) {
|
||||
rendered.push(
|
||||
`## ${title}\n\n`,
|
||||
@@ -608,17 +612,17 @@ const renderNotes = (notes) => {
|
||||
}
|
||||
};
|
||||
|
||||
renderSection('Breaking Changes', notes.breaking);
|
||||
renderSection('Features', notes.feat);
|
||||
renderSection('Fixes', notes.fix);
|
||||
renderSection('Other Changes', notes.other);
|
||||
renderSection('Breaking Changes', notes.breaking, unique);
|
||||
renderSection('Features', notes.feat, unique);
|
||||
renderSection('Fixes', notes.fix, unique);
|
||||
renderSection('Other Changes', notes.other, unique);
|
||||
|
||||
if (notes.docs.length) {
|
||||
const docs = notes.docs.map(commit => renderLink(commit)).sort();
|
||||
rendered.push('## Documentation\n\n', ` * Documentation changes: ${docs.join(', ')}\n`, '\n');
|
||||
}
|
||||
|
||||
renderSection('Unknown', notes.unknown);
|
||||
renderSection('Unknown', notes.unknown, unique);
|
||||
|
||||
return rendered.join('');
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
"""A wrapper script around clang-format, suitable for linting multiple files
|
||||
and to use for continuous integration.
|
||||
|
||||
This is an alternative API for the clang-format command line.
|
||||
It runs over multiple files and directories in parallel.
|
||||
A diff output is produced and a sensible exit code is returned.
|
||||
@@ -11,6 +12,7 @@ from __future__ import print_function, unicode_literals
|
||||
import argparse
|
||||
import codecs
|
||||
import difflib
|
||||
import errno
|
||||
import fnmatch
|
||||
import io
|
||||
import multiprocessing
|
||||
@@ -26,13 +28,28 @@ from functools import partial
|
||||
from lib.util import get_buildtools_executable
|
||||
|
||||
DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,mm'
|
||||
|
||||
DEFAULT_CLANG_FORMAT_IGNORE = '.clang-format-ignore'
|
||||
|
||||
class ExitStatus:
|
||||
SUCCESS = 0
|
||||
DIFF = 1
|
||||
TROUBLE = 2
|
||||
|
||||
def excludes_from_file(ignore_file):
|
||||
excludes = []
|
||||
try:
|
||||
with io.open(ignore_file, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
pattern = line.rstrip()
|
||||
if not pattern:
|
||||
continue
|
||||
excludes.append(pattern)
|
||||
except EnvironmentError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
return excludes
|
||||
|
||||
def list_files(files, recursive=False, extensions=None, exclude=None):
|
||||
if extensions is None:
|
||||
@@ -77,15 +94,13 @@ def make_diff(diff_file, original, reformatted):
|
||||
|
||||
class DiffError(Exception):
|
||||
def __init__(self, message, errs=None):
|
||||
# pylint: disable=R1725
|
||||
super(DiffError, self).__init__(message)
|
||||
super().__init__(message)
|
||||
self.errs = errs or []
|
||||
|
||||
|
||||
class UnexpectedError(Exception):
|
||||
def __init__(self, message, exc=None):
|
||||
# pylint: disable=R1725
|
||||
super(UnexpectedError, self).__init__(message)
|
||||
super().__init__(message)
|
||||
self.formatted_traceback = traceback.format_exc()
|
||||
self.exc = exc
|
||||
|
||||
@@ -112,6 +127,11 @@ def run_clang_format_diff(args, file_name):
|
||||
invocation = [args.clang_format_executable, file_name]
|
||||
if args.fix:
|
||||
invocation.append('-i')
|
||||
if args.style:
|
||||
invocation.extend(['--style', args.style])
|
||||
if args.dry_run:
|
||||
print(" ".join(invocation))
|
||||
return [], []
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
' '.join(invocation),
|
||||
@@ -121,19 +141,13 @@ def run_clang_format_diff(args, file_name):
|
||||
shell=True)
|
||||
except OSError as exc:
|
||||
# pylint: disable=W0707
|
||||
raise DiffError(str(exc))
|
||||
proc_stdout = proc.stdout
|
||||
proc_stderr = proc.stderr
|
||||
if sys.version_info[0] == 3:
|
||||
proc_stdout = proc_stdout.detach()
|
||||
proc_stderr = proc_stderr.detach()
|
||||
# make the pipes compatible with Python 3,
|
||||
# reading lines should output unicode
|
||||
encoding = 'utf-8'
|
||||
proc_stdout = codecs.getreader(encoding)(proc_stdout)
|
||||
proc_stderr = codecs.getreader(encoding)(proc_stderr)
|
||||
outs = list(proc_stdout.readlines())
|
||||
errs = list(proc_stderr.readlines())
|
||||
raise DiffError(
|
||||
"Command '{}' failed to start: {}".format(
|
||||
subprocess.list2cmdline(invocation), exc
|
||||
)
|
||||
)
|
||||
outs = list(proc.stdout.readlines())
|
||||
errs = list(proc.stderr.readlines())
|
||||
proc.wait()
|
||||
if proc.returncode:
|
||||
raise DiffError("clang-format exited with status {}: '{}'".format(
|
||||
@@ -212,6 +226,11 @@ def main():
|
||||
'--recursive',
|
||||
action='store_true',
|
||||
help='run recursively over directories')
|
||||
parser.add_argument(
|
||||
'-d',
|
||||
'--dry-run',
|
||||
action='store_true',
|
||||
help='just print the list of files')
|
||||
parser.add_argument('files', metavar='file', nargs='+')
|
||||
parser.add_argument(
|
||||
'-q',
|
||||
@@ -242,6 +261,10 @@ def main():
|
||||
default=[],
|
||||
help='exclude paths matching the given glob-like pattern(s)'
|
||||
' from recursive search')
|
||||
parser.add_argument(
|
||||
'--style',
|
||||
help='formatting style to apply '
|
||||
'(LLVM/Google/Chromium/Mozilla/WebKit)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -269,13 +292,14 @@ def main():
|
||||
|
||||
parse_files = []
|
||||
if args.changed:
|
||||
popen = subprocess.Popen(
|
||||
'git diff --name-only --cached',
|
||||
stdout = subprocess.Popen(
|
||||
"git diff --name-only --cached",
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
shell=True
|
||||
)
|
||||
for line in popen.stdout:
|
||||
shell=True,
|
||||
universal_newlines=True
|
||||
).communicate()[0].split("\n")
|
||||
for line in stdout:
|
||||
file_name = line.rstrip()
|
||||
# don't check deleted files
|
||||
if os.path.isfile(file_name):
|
||||
@@ -284,14 +308,17 @@ def main():
|
||||
else:
|
||||
parse_files = args.files
|
||||
|
||||
excludes = excludes_from_file(DEFAULT_CLANG_FORMAT_IGNORE)
|
||||
excludes.extend(args.exclude)
|
||||
|
||||
files = list_files(
|
||||
parse_files,
|
||||
recursive=args.recursive,
|
||||
exclude=args.exclude,
|
||||
exclude=excludes,
|
||||
extensions=args.extensions.split(','))
|
||||
|
||||
if not files:
|
||||
return 0
|
||||
return ExitStatus.SUCCESS
|
||||
|
||||
njobs = args.j
|
||||
if njobs == 0:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import chalk from 'chalk';
|
||||
import * as childProcess from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import * as klaw from 'klaw';
|
||||
@@ -143,7 +142,7 @@ async function runClangTidy (
|
||||
jobs: number = 1
|
||||
): Promise<boolean> {
|
||||
const cmd = path.resolve(LLVM_BIN, 'clang-tidy');
|
||||
const args = [`-p=${outDir}`];
|
||||
const args = [`-p=${outDir}`, '--use-color'];
|
||||
|
||||
if (checks) args.push(`--checks=${checks}`);
|
||||
|
||||
@@ -202,38 +201,7 @@ async function runClangTidy (
|
||||
while (filenames) {
|
||||
results.push(
|
||||
await spawnAsync(cmd, [...args, ...filenames], {}).then((result) => {
|
||||
// We lost color, so recolorize because it's much more legible
|
||||
// There's a --use-color flag for clang-tidy but it has no effect
|
||||
// on Windows at the moment, so just recolor for everyone
|
||||
let state = null;
|
||||
|
||||
for (const line of result.stdout.split('\n')) {
|
||||
if (line.includes(' warning: ')) {
|
||||
console.log(
|
||||
line
|
||||
.split(' warning: ')
|
||||
.map((part) => chalk.whiteBright(part))
|
||||
.join(chalk.magentaBright(' warning: '))
|
||||
);
|
||||
state = 'code-line';
|
||||
} else if (line.includes(' note: ')) {
|
||||
const lineParts = line.split(' note: ');
|
||||
lineParts[0] = chalk.whiteBright(lineParts[0]);
|
||||
console.log(lineParts.join(chalk.grey(' note: ')));
|
||||
state = 'code-line';
|
||||
} else if (line.startsWith('error:')) {
|
||||
console.log(
|
||||
chalk.redBright('error: ') + line.split(' ').slice(1).join(' ')
|
||||
);
|
||||
} else if (state === 'code-line') {
|
||||
console.log(line);
|
||||
state = 'post-code-line';
|
||||
} else if (state === 'post-code-line') {
|
||||
console.log(chalk.greenBright(line));
|
||||
} else {
|
||||
console.log(line);
|
||||
}
|
||||
}
|
||||
console.log(result.stdout);
|
||||
|
||||
if (result.status !== 0) {
|
||||
console.error(result.stderr);
|
||||
|
||||
@@ -3673,7 +3673,12 @@ void WebContents::EnumerateDirectory(
|
||||
|
||||
bool WebContents::IsFullscreenForTabOrPending(
|
||||
const content::WebContents* source) {
|
||||
return html_fullscreen_;
|
||||
bool transition_fs = owner_window()
|
||||
? owner_window()->fullscreen_transition_state() !=
|
||||
NativeWindow::FullScreenTransitionState::NONE
|
||||
: false;
|
||||
|
||||
return html_fullscreen_ || transition_fs;
|
||||
}
|
||||
|
||||
bool WebContents::TakeFocus(content::WebContents* source, bool reverse) {
|
||||
@@ -3995,9 +4000,8 @@ void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
? !web_preferences->ShouldDisableHtmlFullscreenWindowResize()
|
||||
: true;
|
||||
|
||||
if (html_fullscreenable) {
|
||||
if (html_fullscreenable)
|
||||
owner_window_->SetFullScreen(enter_fullscreen);
|
||||
}
|
||||
|
||||
UpdateHtmlApiFullscreen(enter_fullscreen);
|
||||
native_fullscreen_ = false;
|
||||
|
||||
@@ -718,6 +718,15 @@ std::string NativeWindow::GetAccessibleTitle() {
|
||||
return base::UTF16ToUTF8(accessible_title_);
|
||||
}
|
||||
|
||||
void NativeWindow::HandlePendingFullscreenTransitions() {
|
||||
if (pending_transitions_.empty())
|
||||
return;
|
||||
|
||||
bool next_transition = pending_transitions_.front();
|
||||
pending_transitions_.pop();
|
||||
SetFullScreen(next_transition);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t NativeWindow::next_id_ = 0;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -317,6 +318,17 @@ class NativeWindow : public base::SupportsUserData,
|
||||
observers_.RemoveObserver(obs);
|
||||
}
|
||||
|
||||
enum class FullScreenTransitionState { ENTERING, EXITING, NONE };
|
||||
|
||||
// Handle fullscreen transitions.
|
||||
void HandlePendingFullscreenTransitions();
|
||||
void set_fullscreen_transition_state(FullScreenTransitionState state) {
|
||||
fullscreen_transition_state_ = state;
|
||||
}
|
||||
FullScreenTransitionState fullscreen_transition_state() const {
|
||||
return fullscreen_transition_state_;
|
||||
}
|
||||
|
||||
views::Widget* widget() const { return widget_.get(); }
|
||||
views::View* content_view() const { return content_view_; }
|
||||
|
||||
@@ -375,6 +387,10 @@ class NativeWindow : public base::SupportsUserData,
|
||||
// The "titleBarStyle" option.
|
||||
TitleBarStyle title_bar_style_ = TitleBarStyle::kNormal;
|
||||
|
||||
std::queue<bool> pending_transitions_;
|
||||
FullScreenTransitionState fullscreen_transition_state_ =
|
||||
FullScreenTransitionState::NONE;
|
||||
|
||||
private:
|
||||
std::unique_ptr<views::Widget> widget_;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -166,17 +165,14 @@ class NativeWindowMac : public NativeWindow,
|
||||
|
||||
void UpdateVibrancyRadii(bool fullscreen);
|
||||
|
||||
void UpdateWindowOriginalFrame();
|
||||
|
||||
// Set the attribute of NSWindow while work around a bug of zoom button.
|
||||
bool HasStyleMask(NSUInteger flag) const;
|
||||
void SetStyleMask(bool on, NSUInteger flag);
|
||||
void SetCollectionBehavior(bool on, NSUInteger flag);
|
||||
void SetWindowLevel(int level);
|
||||
|
||||
enum class FullScreenTransitionState { ENTERING, EXITING, NONE };
|
||||
|
||||
// Handle fullscreen transitions.
|
||||
void SetFullScreenTransitionState(FullScreenTransitionState state);
|
||||
void HandlePendingFullscreenTransitions();
|
||||
bool HandleDeferredClose();
|
||||
void SetHasDeferredWindowClose(bool defer_close) {
|
||||
has_deferred_window_close_ = defer_close;
|
||||
@@ -247,13 +243,6 @@ class NativeWindowMac : public NativeWindow,
|
||||
bool zoom_to_page_width_ = false;
|
||||
absl::optional<gfx::Point> traffic_light_position_;
|
||||
|
||||
std::queue<bool> pending_transitions_;
|
||||
FullScreenTransitionState fullscreen_transition_state() const {
|
||||
return fullscreen_transition_state_;
|
||||
}
|
||||
FullScreenTransitionState fullscreen_transition_state_ =
|
||||
FullScreenTransitionState::NONE;
|
||||
|
||||
// Trying to close an NSWindow during a fullscreen transition will cause the
|
||||
// window to lock up. Use this to track if CloseWindow was called during a
|
||||
// fullscreen transition, to defer the -[NSWindow close] call until the
|
||||
|
||||
@@ -447,7 +447,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||
SetContentView(new views::View());
|
||||
AddContentViewLayers();
|
||||
|
||||
original_frame_ = [window_ frame];
|
||||
UpdateWindowOriginalFrame();
|
||||
original_level_ = [window_ level];
|
||||
}
|
||||
|
||||
@@ -582,11 +582,6 @@ bool NativeWindowMac::IsVisible() {
|
||||
return [window_ isVisible] && !occluded && !IsMinimized();
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetFullScreenTransitionState(
|
||||
FullScreenTransitionState state) {
|
||||
fullscreen_transition_state_ = state;
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsEnabled() {
|
||||
return [window_ attachedSheet] == nil;
|
||||
}
|
||||
@@ -614,7 +609,7 @@ void NativeWindowMac::Maximize() {
|
||||
|
||||
// Take note of the current window size
|
||||
if (IsNormal())
|
||||
original_frame_ = [window_ frame];
|
||||
UpdateWindowOriginalFrame();
|
||||
[window_ zoom:nil];
|
||||
|
||||
if (!is_visible) {
|
||||
@@ -658,7 +653,7 @@ void NativeWindowMac::Minimize() {
|
||||
|
||||
// Take note of the current window size
|
||||
if (IsNormal())
|
||||
original_frame_ = [window_ frame];
|
||||
UpdateWindowOriginalFrame();
|
||||
[window_ miniaturize:nil];
|
||||
}
|
||||
|
||||
@@ -670,15 +665,6 @@ bool NativeWindowMac::IsMinimized() {
|
||||
return [window_ isMiniaturized];
|
||||
}
|
||||
|
||||
void NativeWindowMac::HandlePendingFullscreenTransitions() {
|
||||
if (pending_transitions_.empty())
|
||||
return;
|
||||
|
||||
bool next_transition = pending_transitions_.front();
|
||||
pending_transitions_.pop();
|
||||
SetFullScreen(next_transition);
|
||||
}
|
||||
|
||||
bool NativeWindowMac::HandleDeferredClose() {
|
||||
if (has_deferred_window_close_) {
|
||||
SetHasDeferredWindowClose(false);
|
||||
@@ -711,7 +697,7 @@ void NativeWindowMac::SetFullScreen(bool fullscreen) {
|
||||
|
||||
// Take note of the current window size
|
||||
if (IsNormal())
|
||||
original_frame_ = [window_ frame];
|
||||
UpdateWindowOriginalFrame();
|
||||
|
||||
// This needs to be set here because it can be the case that
|
||||
// SetFullScreen is called by a user before windowWillEnterFullScreen
|
||||
@@ -747,6 +733,7 @@ void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) {
|
||||
|
||||
[window_ setFrame:cocoa_bounds display:YES animate:animate];
|
||||
user_set_bounds_maximized_ = IsMaximized() ? true : false;
|
||||
UpdateWindowOriginalFrame();
|
||||
}
|
||||
|
||||
gfx::Rect NativeWindowMac::GetBounds() {
|
||||
@@ -1019,7 +1006,7 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
|
||||
|
||||
// Take note of the current window size and level
|
||||
if (IsNormal()) {
|
||||
original_frame_ = [window_ frame];
|
||||
UpdateWindowOriginalFrame();
|
||||
original_level_ = [window_ level];
|
||||
}
|
||||
|
||||
@@ -1416,6 +1403,10 @@ void NativeWindowMac::UpdateVibrancyRadii(bool fullscreen) {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::UpdateWindowOriginalFrame() {
|
||||
original_frame_ = [window_ frame];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetVibrancy(const std::string& type) {
|
||||
NSVisualEffectView* vibrantView = [window_ vibrantView];
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 21,0,0,20220603
|
||||
PRODUCTVERSION 21,0,0,20220603
|
||||
FILEVERSION 21,0,0,20220610
|
||||
PRODUCTVERSION 21,0,0,20220610
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -203,6 +203,7 @@ using FullScreenTransitionState =
|
||||
// windowDidDeminiaturize
|
||||
level_ = [window level];
|
||||
shell_->SetWindowLevel(NSNormalWindowLevel);
|
||||
shell_->UpdateWindowOriginalFrame();
|
||||
}
|
||||
|
||||
- (void)windowDidMiniaturize:(NSNotification*)notification {
|
||||
@@ -237,7 +238,7 @@ using FullScreenTransitionState =
|
||||
// Store resizable mask so it can be restored after exiting fullscreen.
|
||||
is_resizable_ = shell_->HasStyleMask(NSWindowStyleMaskResizable);
|
||||
|
||||
shell_->SetFullScreenTransitionState(FullScreenTransitionState::ENTERING);
|
||||
shell_->set_fullscreen_transition_state(FullScreenTransitionState::ENTERING);
|
||||
|
||||
shell_->NotifyWindowWillEnterFullScreen();
|
||||
|
||||
@@ -246,7 +247,7 @@ using FullScreenTransitionState =
|
||||
}
|
||||
|
||||
- (void)windowDidEnterFullScreen:(NSNotification*)notification {
|
||||
shell_->SetFullScreenTransitionState(FullScreenTransitionState::NONE);
|
||||
shell_->set_fullscreen_transition_state(FullScreenTransitionState::NONE);
|
||||
|
||||
shell_->NotifyWindowEnterFullScreen();
|
||||
|
||||
@@ -257,13 +258,13 @@ using FullScreenTransitionState =
|
||||
}
|
||||
|
||||
- (void)windowWillExitFullScreen:(NSNotification*)notification {
|
||||
shell_->SetFullScreenTransitionState(FullScreenTransitionState::EXITING);
|
||||
shell_->set_fullscreen_transition_state(FullScreenTransitionState::EXITING);
|
||||
|
||||
shell_->NotifyWindowWillLeaveFullScreen();
|
||||
}
|
||||
|
||||
- (void)windowDidExitFullScreen:(NSNotification*)notification {
|
||||
shell_->SetFullScreenTransitionState(FullScreenTransitionState::NONE);
|
||||
shell_->set_fullscreen_transition_state(FullScreenTransitionState::NONE);
|
||||
|
||||
shell_->SetResizable(is_resizable_);
|
||||
shell_->NotifyWindowLeaveFullScreen();
|
||||
|
||||
@@ -1228,6 +1228,7 @@ describe('BrowserWindow module', () => {
|
||||
await resize;
|
||||
expectBoundsEqual(w.getNormalBounds(), w.getBounds());
|
||||
});
|
||||
|
||||
it('checks normal bounds after move', async () => {
|
||||
const pos = [10, 10];
|
||||
const move = emittedOnce(w, 'move');
|
||||
@@ -1246,6 +1247,51 @@ describe('BrowserWindow module', () => {
|
||||
await maximize;
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it('updates normal bounds after resize and maximize', async () => {
|
||||
const size = [300, 400];
|
||||
const resize = emittedOnce(w, 'resize');
|
||||
w.setSize(size[0], size[1]);
|
||||
await resize;
|
||||
const original = w.getBounds();
|
||||
|
||||
const maximize = emittedOnce(w, 'maximize');
|
||||
w.maximize();
|
||||
await maximize;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
const bounds = w.getBounds();
|
||||
|
||||
expect(normal).to.deep.equal(original);
|
||||
expect(normal).to.not.deep.equal(bounds);
|
||||
|
||||
const close = emittedOnce(w, 'close');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
|
||||
it('updates normal bounds after move and maximize', async () => {
|
||||
const pos = [10, 10];
|
||||
const move = emittedOnce(w, 'move');
|
||||
w.setPosition(pos[0], pos[1]);
|
||||
await move;
|
||||
const original = w.getBounds();
|
||||
|
||||
const maximize = emittedOnce(w, 'maximize');
|
||||
w.maximize();
|
||||
await maximize;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
const bounds = w.getBounds();
|
||||
|
||||
expect(normal).to.deep.equal(original);
|
||||
expect(normal).to.not.deep.equal(bounds);
|
||||
|
||||
const close = emittedOnce(w, 'close');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
|
||||
it('checks normal bounds when unmaximized', async () => {
|
||||
const bounds = w.getBounds();
|
||||
w.once('maximize', () => {
|
||||
@@ -1257,6 +1303,7 @@ describe('BrowserWindow module', () => {
|
||||
await unmaximize;
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it('does not change size for a frameless window with min size', async () => {
|
||||
w.destroy();
|
||||
w = new BrowserWindow({
|
||||
@@ -1277,6 +1324,7 @@ describe('BrowserWindow module', () => {
|
||||
await unmaximize;
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it('correctly checks transparent window maximization state', async () => {
|
||||
w.destroy();
|
||||
w = new BrowserWindow({
|
||||
@@ -1296,6 +1344,7 @@ describe('BrowserWindow module', () => {
|
||||
await unmaximize;
|
||||
expect(w.isMaximized()).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns the correct value for windows with an aspect ratio', async () => {
|
||||
w.destroy();
|
||||
w = new BrowserWindow({
|
||||
@@ -1325,6 +1374,41 @@ describe('BrowserWindow module', () => {
|
||||
await minimize;
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it('updates normal bounds after move and minimize', async () => {
|
||||
const pos = [10, 10];
|
||||
const move = emittedOnce(w, 'move');
|
||||
w.setPosition(pos[0], pos[1]);
|
||||
await move;
|
||||
const original = w.getBounds();
|
||||
|
||||
const minimize = emittedOnce(w, 'minimize');
|
||||
w.minimize();
|
||||
await minimize;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
|
||||
expect(original).to.deep.equal(normal);
|
||||
expectBoundsEqual(normal, w.getBounds());
|
||||
});
|
||||
|
||||
it('updates normal bounds after resize and minimize', async () => {
|
||||
const size = [300, 400];
|
||||
const resize = emittedOnce(w, 'resize');
|
||||
w.setSize(size[0], size[1]);
|
||||
await resize;
|
||||
const original = w.getBounds();
|
||||
|
||||
const minimize = emittedOnce(w, 'minimize');
|
||||
w.minimize();
|
||||
await minimize;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
|
||||
expect(original).to.deep.equal(normal);
|
||||
expectBoundsEqual(normal, w.getBounds());
|
||||
});
|
||||
|
||||
it('checks normal bounds when restored', async () => {
|
||||
const bounds = w.getBounds();
|
||||
w.once('minimize', () => {
|
||||
@@ -1336,6 +1420,7 @@ describe('BrowserWindow module', () => {
|
||||
await restore;
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it('does not change size for a frameless window with min size', async () => {
|
||||
w.destroy();
|
||||
w = new BrowserWindow({
|
||||
@@ -1381,6 +1466,50 @@ describe('BrowserWindow module', () => {
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it('updates normal bounds after resize and fullscreen', async () => {
|
||||
const size = [300, 400];
|
||||
const resize = emittedOnce(w, 'resize');
|
||||
w.setSize(size[0], size[1]);
|
||||
await resize;
|
||||
const original = w.getBounds();
|
||||
|
||||
const fsc = emittedOnce(w, 'enter-full-screen');
|
||||
w.fullScreen = true;
|
||||
await fsc;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
const bounds = w.getBounds();
|
||||
|
||||
expect(normal).to.deep.equal(original);
|
||||
expect(normal).to.not.deep.equal(bounds);
|
||||
|
||||
const close = emittedOnce(w, 'close');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
|
||||
it('updates normal bounds after move and fullscreen', async () => {
|
||||
const pos = [10, 10];
|
||||
const move = emittedOnce(w, 'move');
|
||||
w.setPosition(pos[0], pos[1]);
|
||||
await move;
|
||||
const original = w.getBounds();
|
||||
|
||||
const fsc = emittedOnce(w, 'enter-full-screen');
|
||||
w.fullScreen = true;
|
||||
await fsc;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
const bounds = w.getBounds();
|
||||
|
||||
expect(normal).to.deep.equal(original);
|
||||
expect(normal).to.not.deep.equal(bounds);
|
||||
|
||||
const close = emittedOnce(w, 'close');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
|
||||
it('checks normal bounds when unfullscreen\'ed', async () => {
|
||||
const bounds = w.getBounds();
|
||||
w.once('enter-full-screen', () => {
|
||||
@@ -1418,6 +1547,50 @@ describe('BrowserWindow module', () => {
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it('updates normal bounds after resize and fullscreen', async () => {
|
||||
const size = [300, 400];
|
||||
const resize = emittedOnce(w, 'resize');
|
||||
w.setSize(size[0], size[1]);
|
||||
await resize;
|
||||
const original = w.getBounds();
|
||||
|
||||
const fsc = emittedOnce(w, 'enter-full-screen');
|
||||
w.setFullScreen(true);
|
||||
await fsc;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
const bounds = w.getBounds();
|
||||
|
||||
expect(normal).to.deep.equal(original);
|
||||
expect(normal).to.not.deep.equal(bounds);
|
||||
|
||||
const close = emittedOnce(w, 'close');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
|
||||
it('updates normal bounds after move and fullscreen', async () => {
|
||||
const pos = [10, 10];
|
||||
const move = emittedOnce(w, 'move');
|
||||
w.setPosition(pos[0], pos[1]);
|
||||
await move;
|
||||
const original = w.getBounds();
|
||||
|
||||
const fsc = emittedOnce(w, 'enter-full-screen');
|
||||
w.setFullScreen(true);
|
||||
await fsc;
|
||||
|
||||
const normal = w.getNormalBounds();
|
||||
const bounds = w.getBounds();
|
||||
|
||||
expect(normal).to.deep.equal(original);
|
||||
expect(normal).to.not.deep.equal(bounds);
|
||||
|
||||
const close = emittedOnce(w, 'close');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
|
||||
it('checks normal bounds when unfullscreen\'ed', async () => {
|
||||
const bounds = w.getBounds();
|
||||
w.show();
|
||||
@@ -4731,19 +4904,80 @@ describe('BrowserWindow module', () => {
|
||||
expect(w.isFullScreen()).to.be.false('is fullscreen');
|
||||
});
|
||||
|
||||
it('handles several HTML fullscreen transitions', async () => {
|
||||
const w = new BrowserWindow();
|
||||
await w.loadFile(path.join(fixtures, 'pages', 'a.html'));
|
||||
|
||||
expect(w.isFullScreen()).to.be.false('is fullscreen');
|
||||
|
||||
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
|
||||
const leaveFullScreen = emittedOnce(w, 'leave-full-screen');
|
||||
|
||||
await w.webContents.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||
await enterFullScreen;
|
||||
await w.webContents.executeJavaScript('document.exitFullscreen()', true);
|
||||
await leaveFullScreen;
|
||||
|
||||
expect(w.isFullScreen()).to.be.false('is fullscreen');
|
||||
|
||||
await delay();
|
||||
|
||||
await w.webContents.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||
await enterFullScreen;
|
||||
await w.webContents.executeJavaScript('document.exitFullscreen()', true);
|
||||
await leaveFullScreen;
|
||||
|
||||
expect(w.isFullScreen()).to.be.false('is fullscreen');
|
||||
});
|
||||
|
||||
it('handles several transitions in close proximity', async () => {
|
||||
const w = new BrowserWindow();
|
||||
|
||||
expect(w.isFullScreen()).to.be.false('is fullscreen');
|
||||
|
||||
const enterFS = emittedNTimes(w, 'enter-full-screen', 2);
|
||||
const leaveFS = emittedNTimes(w, 'leave-full-screen', 2);
|
||||
|
||||
w.setFullScreen(true);
|
||||
w.setFullScreen(false);
|
||||
w.setFullScreen(true);
|
||||
w.setFullScreen(false);
|
||||
|
||||
const enterFullScreen = emittedNTimes(w, 'enter-full-screen', 2);
|
||||
await enterFullScreen;
|
||||
await Promise.all([enterFS, leaveFS]);
|
||||
|
||||
expect(w.isFullScreen()).to.be.true('not fullscreen');
|
||||
expect(w.isFullScreen()).to.be.false('not fullscreen');
|
||||
});
|
||||
|
||||
it('handles several chromium-initiated transitions in close proximity', async () => {
|
||||
const w = new BrowserWindow();
|
||||
await w.loadFile(path.join(fixtures, 'pages', 'a.html'));
|
||||
|
||||
expect(w.isFullScreen()).to.be.false('is fullscreen');
|
||||
|
||||
let enterCount = 0;
|
||||
let exitCount = 0;
|
||||
|
||||
const done = new Promise<void>(resolve => {
|
||||
const checkDone = () => {
|
||||
if (enterCount === 2 && exitCount === 2) resolve();
|
||||
};
|
||||
|
||||
w.webContents.on('enter-html-full-screen', () => {
|
||||
enterCount++;
|
||||
checkDone();
|
||||
});
|
||||
|
||||
w.webContents.on('leave-html-full-screen', () => {
|
||||
exitCount++;
|
||||
checkDone();
|
||||
});
|
||||
});
|
||||
|
||||
await w.webContents.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||
await w.webContents.executeJavaScript('document.exitFullscreen()');
|
||||
await w.webContents.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||
await w.webContents.executeJavaScript('document.exitFullscreen()');
|
||||
await done;
|
||||
});
|
||||
|
||||
it('does not crash when exiting simpleFullScreen (properties)', async () => {
|
||||
|
||||
@@ -230,7 +230,9 @@ describe('webFrameMain module', () => {
|
||||
// Keep reference to mainFrame alive throughout crash and recovery.
|
||||
const { mainFrame } = w.webContents;
|
||||
await w.webContents.loadURL(server.url);
|
||||
const crashEvent = emittedOnce(w.webContents, 'render-process-gone');
|
||||
w.webContents.forcefullyCrashRenderer();
|
||||
await crashEvent;
|
||||
await w.webContents.loadURL(server.url);
|
||||
// Log just to keep mainFrame in scope.
|
||||
console.log('mainFrame.url', mainFrame.url);
|
||||
@@ -244,7 +246,9 @@ describe('webFrameMain module', () => {
|
||||
// Keep reference to mainFrame alive throughout crash and recovery.
|
||||
const { mainFrame } = w.webContents;
|
||||
await w.webContents.loadURL(server.url);
|
||||
const crashEvent = emittedOnce(w.webContents, 'render-process-gone');
|
||||
w.webContents.forcefullyCrashRenderer();
|
||||
await crashEvent;
|
||||
// A short wait seems to be required to reproduce the crash.
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
await w.webContents.loadURL(crossOriginUrl);
|
||||
|
||||
@@ -10,7 +10,7 @@ import * as url from 'url';
|
||||
import * as ChildProcess from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
import { promisify } from 'util';
|
||||
import { ifit, ifdescribe, delay, defer } from './spec-helpers';
|
||||
import { ifit, ifdescribe, defer, delay } from './spec-helpers';
|
||||
import { AddressInfo } from 'net';
|
||||
import { PipeTransport } from './pipe-transport';
|
||||
|
||||
@@ -1590,7 +1590,7 @@ describe('iframe using HTML fullscreen API while window is OS-fullscreened', ()
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('can fullscreen from out-of-process iframes (OOPIFs)', async () => {
|
||||
ifit(process.platform !== 'darwin')('can fullscreen from out-of-process iframes (non-macOS)', async () => {
|
||||
const fullscreenChange = emittedOnce(ipcMain, 'fullscreenChange');
|
||||
const html =
|
||||
'<iframe style="width: 0" frameborder=0 src="http://localhost:8989" allowfullscreen></iframe>';
|
||||
@@ -1614,8 +1614,37 @@ describe('iframe using HTML fullscreen API while window is OS-fullscreened', ()
|
||||
expect(width).to.equal(0);
|
||||
});
|
||||
|
||||
ifit(process.platform === 'darwin')('can fullscreen from out-of-process iframes (macOS)', async () => {
|
||||
await emittedOnce(w, 'enter-full-screen');
|
||||
const fullscreenChange = emittedOnce(ipcMain, 'fullscreenChange');
|
||||
const html =
|
||||
'<iframe style="width: 0" frameborder=0 src="http://localhost:8989" allowfullscreen></iframe>';
|
||||
w.loadURL(`data:text/html,${html}`);
|
||||
await fullscreenChange;
|
||||
|
||||
const fullscreenWidth = await w.webContents.executeJavaScript(
|
||||
"document.querySelector('iframe').offsetWidth"
|
||||
);
|
||||
expect(fullscreenWidth > 0).to.be.true();
|
||||
|
||||
await w.webContents.executeJavaScript(
|
||||
"document.querySelector('iframe').contentWindow.postMessage('exitFullscreen', '*')"
|
||||
);
|
||||
await emittedOnce(w.webContents, 'leave-html-full-screen');
|
||||
|
||||
const width = await w.webContents.executeJavaScript(
|
||||
"document.querySelector('iframe').offsetWidth"
|
||||
);
|
||||
expect(width).to.equal(0);
|
||||
|
||||
w.setFullScreen(false);
|
||||
await emittedOnce(w, 'leave-full-screen');
|
||||
});
|
||||
|
||||
// TODO(jkleinsc) fix this flaky test on WOA
|
||||
ifit(process.platform !== 'win32' || process.arch !== 'arm64')('can fullscreen from in-process iframes', async () => {
|
||||
if (process.platform === 'darwin') await emittedOnce(w, 'enter-full-screen');
|
||||
|
||||
const fullscreenChange = emittedOnce(ipcMain, 'fullscreenChange');
|
||||
w.loadFile(path.join(fixturesPath, 'pages', 'fullscreen-ipif.html'));
|
||||
await fullscreenChange;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<div id="div">
|
||||
WebView
|
||||
</div>
|
||||
<video></video>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
const {ipcRenderer} = require('electron')
|
||||
ipcRenderer.send('webview-ready')
|
||||
|
||||
@@ -426,11 +426,16 @@ describe('<webview> tag', function () {
|
||||
contextIsolation: false
|
||||
}
|
||||
});
|
||||
|
||||
const attachPromise = emittedOnce(w.webContents, 'did-attach-webview');
|
||||
const loadPromise = emittedOnce(w.webContents, 'did-finish-load');
|
||||
const readyPromise = emittedOnce(ipcMain, 'webview-ready');
|
||||
|
||||
w.loadFile(path.join(__dirname, 'fixtures', 'webview', 'fullscreen', 'main.html'));
|
||||
|
||||
const [, webview] = await attachPromise;
|
||||
await readyPromise;
|
||||
await Promise.all([readyPromise, loadPromise]);
|
||||
|
||||
return [w, webview];
|
||||
};
|
||||
|
||||
@@ -442,17 +447,38 @@ describe('<webview> tag', function () {
|
||||
closeAllWindows();
|
||||
});
|
||||
|
||||
it('should make parent frame element fullscreen too', async () => {
|
||||
ifit(process.platform !== 'darwin')('should make parent frame element fullscreen too (non-macOS)', async () => {
|
||||
const [w, webview] = await loadWebViewWindow();
|
||||
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.false();
|
||||
|
||||
const parentFullscreen = emittedOnce(ipcMain, 'fullscreenchange');
|
||||
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||
await parentFullscreen;
|
||||
|
||||
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.true();
|
||||
|
||||
const close = emittedOnce(w, 'closed');
|
||||
w.close();
|
||||
await emittedOnce(w, 'closed');
|
||||
await close;
|
||||
});
|
||||
|
||||
ifit(process.platform === 'darwin')('should make parent frame element fullscreen too (macOS)', async () => {
|
||||
const [w, webview] = await loadWebViewWindow();
|
||||
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.false();
|
||||
|
||||
const parentFullscreen = emittedOnce(ipcMain, 'fullscreenchange');
|
||||
const enterHTMLFS = emittedOnce(w.webContents, 'enter-html-full-screen');
|
||||
const leaveHTMLFS = emittedOnce(w.webContents, 'leave-html-full-screen');
|
||||
|
||||
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.true();
|
||||
|
||||
await webview.executeJavaScript('document.exitFullscreen()');
|
||||
await Promise.all([enterHTMLFS, leaveHTMLFS, parentFullscreen]);
|
||||
|
||||
const close = emittedOnce(w, 'closed');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
|
||||
// FIXME(zcbenz): Fullscreen events do not work on Linux.
|
||||
@@ -468,8 +494,9 @@ describe('<webview> tag', function () {
|
||||
await delay(0);
|
||||
expect(w.isFullScreen()).to.be.false();
|
||||
|
||||
const close = emittedOnce(w, 'closed');
|
||||
w.close();
|
||||
await emittedOnce(w, 'closed');
|
||||
await close;
|
||||
});
|
||||
|
||||
// Sending ESC via sendInputEvent only works on Windows.
|
||||
@@ -485,8 +512,9 @@ describe('<webview> tag', function () {
|
||||
await delay(0);
|
||||
expect(w.isFullScreen()).to.be.false();
|
||||
|
||||
const close = emittedOnce(w, 'closed');
|
||||
w.close();
|
||||
await emittedOnce(w, 'closed');
|
||||
await close;
|
||||
});
|
||||
|
||||
it('pressing ESC should emit the leave-html-full-screen event', async () => {
|
||||
@@ -513,11 +541,27 @@ describe('<webview> tag', function () {
|
||||
const leaveFSWindow = emittedOnce(w, 'leave-html-full-screen');
|
||||
const leaveFSWebview = emittedOnce(webContents, 'leave-html-full-screen');
|
||||
webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
|
||||
await leaveFSWindow;
|
||||
await leaveFSWebview;
|
||||
await leaveFSWindow;
|
||||
|
||||
const close = emittedOnce(w, 'closed');
|
||||
w.close();
|
||||
await emittedOnce(w, 'closed');
|
||||
await close;
|
||||
});
|
||||
|
||||
it('should support user gesture', async () => {
|
||||
const [w, webview] = await loadWebViewWindow();
|
||||
|
||||
const waitForEnterHtmlFullScreen = emittedOnce(webview, 'enter-html-full-screen');
|
||||
|
||||
const jsScript = "document.querySelector('video').webkitRequestFullscreen()";
|
||||
webview.executeJavaScript(jsScript, true);
|
||||
|
||||
await waitForEnterHtmlFullScreen;
|
||||
|
||||
const close = emittedOnce(w, 'closed');
|
||||
w.close();
|
||||
await close;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
2
spec/fixtures/pages/fullscreen.html
vendored
2
spec/fixtures/pages/fullscreen.html
vendored
@@ -1 +1 @@
|
||||
<video></video>
|
||||
<video></video>
|
||||
@@ -910,20 +910,6 @@ describe('<webview> tag', function () {
|
||||
});
|
||||
|
||||
describe('executeJavaScript', () => {
|
||||
it('should support user gesture', async () => {
|
||||
await loadWebView(webview, {
|
||||
src: `file://${fixtures}/pages/fullscreen.html`
|
||||
});
|
||||
|
||||
// Event handler has to be added before js execution.
|
||||
const waitForEnterHtmlFullScreen = waitForEvent(webview, 'enter-html-full-screen');
|
||||
|
||||
const jsScript = "document.querySelector('video').webkitRequestFullscreen()";
|
||||
webview.executeJavaScript(jsScript, true);
|
||||
|
||||
return waitForEnterHtmlFullScreen;
|
||||
});
|
||||
|
||||
it('can return the result of the executed script', async () => {
|
||||
await loadWebView(webview, {
|
||||
src: 'about:blank'
|
||||
|
||||
Reference in New Issue
Block a user