Compare commits

...

6 commits

Author SHA1 Message Date
Philip Peterson
1d2feae11c
Fix ARM build (#230)
Some checks failed
CodeQL / Analyze (push) Has been cancelled
2026-01-04 09:23:11 -05:00
Quine Global
098176dafb Upgrade electron-drag-click
Some checks are pending
CodeQL / Analyze (push) Waiting to run
2026-01-04 03:57:54 -05:00
Max Horvath
6331c14df9
Fix macOS 26 GPU performance issue by upgrading to Electron 38 (#222)
* Fix macOS 26 GPU performance issue by upgrading to Electron 38

Upgrades Electron from 34.5.1 to 38.6.0 to resolve excessive WindowServer
GPU usage on macOS 26 (Sequoia). This issue was caused by Electron's
override of the private _cornerMask API, which forced the compositor to
treat window masks as dynamic rather than static, resulting in persistent
high GPU load.

Changes:
- Upgrade electron: 34.5.1 → 38.6.0
- Upgrade electron-mksnapshot: 34.5.1 → 38.6.0
- Upgrade @electron/rebuild: ^3.7.1 → ^3.7.2
- Upgrade node-abi: ^3.67.0 → ^3.81.0 (required for Electron 38 support)

The fix was introduced in Electron 36.9.2, 37.6.0, 38.2.0, and all later
versions. We're upgrading to 38.6.0 as it's the latest stable version
compatible with Node 20.11.0.

Fixes: electron/electron#48376

* Use optional chaining

Signed-off-by: Philip Peterson <1326208+philip-peterson@users.noreply.github.com>

---------

Signed-off-by: Philip Peterson <1326208+philip-peterson@users.noreply.github.com>
Co-authored-by: Philip Peterson <1326208+philip-peterson@users.noreply.github.com>
2026-01-04 08:43:36 +00:00
Philip Peterson
3c4b7f30f4
Bump version to 4.0.0-q-canary.8 (#185)
Some checks failed
CodeQL / Analyze (push) Has been cancelled
Co-authored-by: Philip Peterson <philip-peterson@users.noreply.github.com>
2025-08-31 01:00:06 -07:00
Philip Peterson
a495a38db3
Windows compatibility fixes (#183) 2025-08-30 23:07:24 -07:00
Philip Peterson
40cece79ba
Updates to scripts (#180) 2025-08-30 22:52:25 -07:00
14 changed files with 133 additions and 51 deletions

View file

@ -73,6 +73,11 @@ runs:
copy_artifact_path: target
copy_artifact_dest: target
commands: |
# Install Python distutils in the ARM container
sudo apt-get update
sudo apt-get install -y python3-pip python3-setuptools python3-dev
pip3 install setuptools --break-system-packages || pip3 install setuptools
cd target
# TODO upgrade node to 20.11.0 to match NODE_VERSION
wget https://nodejs.org/dist/v18.16.0/node-v18.16.0-linux-${{ inputs.matrix-name }}.tar.xz

View file

@ -97,6 +97,28 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU and binfmt
run: |
# Install qemu-user-static
sudo apt-get update
sudo apt-get install -y qemu-user-static binfmt-support python3-setuptools
# Install distutils for node-gyp
sudo apt-get install -y python3-distutils || sudo apt-get install -y python3-dev python-is-python3
# Download and install binfmt configurations
wget https://github.com/qemu/qemu/raw/master/scripts/qemu-binfmt-conf.sh
chmod +x qemu-binfmt-conf.sh
sudo ./qemu-binfmt-conf.sh --qemu-path /usr/bin --qemu-suffix -static --debian
# Import the binfmt configurations
sudo update-binfmts --import qemu-arm
sudo update-binfmts --import qemu-aarch64
# Verify they exist
ls -la /proc/sys/fs/binfmt_misc/qemu-arm* || true
- name: Build ARMv7l
uses: ./.github/actions/build-linux-arm
env:

View file

@ -84,6 +84,27 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU and binfmt
run: |
# Install qemu-user-static
sudo apt-get update
sudo apt-get install -y qemu-user-static binfmt-support python3-setuptools
# Install distutils for node-gyp
sudo apt-get install -y python3-distutils || sudo apt-get install -y python3-dev python-is-python3
# Download and install binfmt configurations
wget https://github.com/qemu/qemu/raw/master/scripts/qemu-binfmt-conf.sh
chmod +x qemu-binfmt-conf.sh
sudo ./qemu-binfmt-conf.sh --qemu-path /usr/bin --qemu-suffix -static --debian
# Import the binfmt configurations
sudo update-binfmts --import qemu-arm
sudo update-binfmts --import qemu-aarch64
# Verify they exist
ls -la /proc/sys/fs/binfmt_misc/qemu-arm* || true
- name: Build ARMv7l
uses: ./.github/actions/build-linux-arm
env:

View file

@ -190,7 +190,7 @@ app.on('ready', () =>
}
}
]);
app.dock.setMenu(dockMenu);
app.dock?.setMenu(dockMenu);
}
Menu.setApplicationMenu(AppMenu.buildMenu(menu));

View file

@ -65,7 +65,10 @@ export const createMenu = (
Created by Guillermo Rauch
Copyright © 2022 Vercel, Inc.
`.split('\n').map(z => z.trim()).join('\n'),
`
.split('\n')
.map((z) => z.trim())
.join('\n'),
buttons: [],
icon: icon as any
});

View file

@ -2,7 +2,7 @@
"name": "hyper",
"productName": "Hyper",
"description": "A terminal built on web technologies",
"version": "4.0.0-q-canary.6",
"version": "4.0.0-q-canary.8",
"license": "MIT",
"author": {
"name": "ZEIT, Inc.",
@ -20,8 +20,7 @@
"chokidar": "^3.6.0",
"color": "4.2.3",
"default-shell": "1.0.1",
"electron-devtools-installer": "3.2.0",
"quine-electron-drag-click": "1.0.6d",
"electron-devtools-installer": "3.2.1",
"electron-fetch": "1.9.1",
"electron-is-dev": "2.0.0",
"electron-store": "8.2.0",
@ -34,6 +33,7 @@
"os-locale": "5.0.0",
"parse-url": "9.2.0",
"queue": "6.0.2",
"quine-electron-drag-click": "2.0.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"recast": "0.23.11",

View file

@ -27,7 +27,9 @@ import toElectronBackgroundColor from '../utils/to-electron-background-color';
import contextMenuTemplate from './contextmenu';
if (process.platform === 'darwin') {
electronDragClick();
}
export function newWindow(
options_: BrowserWindowConstructorOptions,

View file

@ -353,10 +353,10 @@ eastasianwidth@^0.2.0:
resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
electron-devtools-installer@3.2.0:
version "3.2.0"
resolved "https://registry.npmjs.org/electron-devtools-installer/-/electron-devtools-installer-3.2.0.tgz#acc48d24eb7033fe5af284a19667e73b78d406d0"
integrity sha512-t3UczsYugm4OAbqvdImMCImIMVdFzJAHgbwHpkl5jmfu1izVgUcP/mnrPqJIpEeCK1uZGpt+yHgWEN+9EwoYhQ==
electron-devtools-installer@3.2.1:
version "3.2.1"
resolved "https://registry.npmjs.org/electron-devtools-installer/-/electron-devtools-installer-3.2.1.tgz#338a0ada7b4232ee42cd88fe5cf305c6be95cfe9"
integrity sha512-FaCi+oDCOBTw0gJUsuw5dXW32b2Ekh5jO8lI1NRCQigo3azh2VogsIi0eelMVrP1+LkN/bewyH3Xoo1USjO0eQ==
dependencies:
rimraf "^3.0.2"
semver "^7.2.1"
@ -1219,10 +1219,10 @@ queue@6.0.2:
dependencies:
inherits "~2.0.3"
quine-electron-drag-click@1.0.6d:
version "1.0.6-d"
resolved "https://registry.npmjs.org/quine-electron-drag-click/-/quine-electron-drag-click-1.0.6-d.tgz#210fc244fdf3a11b3ad1b2e2d7d7670176b5e19b"
integrity sha512-2geemTnPP3GuEGzOR/IbbXbTf+JX/VERjerA4r2TuXYHSanNiEbMWSSZ2wD8RllOnp/tBIE+O4CmmPfJ86rYQQ==
quine-electron-drag-click@2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/quine-electron-drag-click/-/quine-electron-drag-click-2.0.0.tgz#c6694a706b4c4eca75277ef2c34d7773476700e1"
integrity sha512-pieh1HawezFDn+cpBgs+RQXeR8wj0h/gZafB3sB9rYRQAHTs9V1R8gIq6u7SjGrn1esiM+iP4cknpzsbk/KQ9w==
dependencies:
bindings "^1.5.0"
node-addon-api "^3.0.2"

13
bin/cp-snapshot.js vendored
View file

@ -1,3 +1,4 @@
const path = require('path');
const fs = require('fs');
const fsPromises = require('fs/promises');
@ -10,24 +11,30 @@ function copySnapshot(pathToElectron, archToCopy) {
const pathToBlobV8 = path.resolve(__dirname, '..', 'cache', archToCopy, v8ContextFileName);
console.log('Copying v8 snapshots from', pathToBlob, 'to', pathToElectron);
fs.mkdirSync(pathToElectron, { recursive: true });
fs.copyFileSync(pathToBlob, path.join(pathToElectron, snapshotFileName));
fs.copyFileSync(pathToBlobV8, path.join(pathToElectron, v8ContextFileName));
}
function getPathToElectron() {
const electronPath = require.resolve('electron');
switch (process.platform) {
case 'darwin':
return path.resolve(
__dirname,
electronPath,
'..',
'node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources'
'..',
'..',
'dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources'
);
case 'win32':
case 'linux':
return path.resolve(__dirname, '..', 'node_modules', 'electron', 'dist');
return path.resolve(electronPath, '..', '..', '..', 'dist');
}
}
function getV8ContextFileName(archToCopy) {
return `snapshot_blob.bin`;
}

26
bin/mk-snapshot.js vendored
View file

@ -15,6 +15,12 @@ const archMap = {
};
async function main() {
const npmConfigArch = process.env.npm_config_arch;
if (!npmConfigArch) {
throw new Error('env var npm_config_arch is not specified')
}
const baseDirPath = path.resolve(__dirname, '..');
console.log('Creating a linked script..');
@ -32,11 +38,25 @@ async function main() {
// Verify if we will be able to use this in `mksnapshot`
vm.runInNewContext(result.snapshotScript, undefined, {filename: snapshotScriptPath, displayErrors: true});
const outputBlobPath = `${baseDirPath}/cache/${process.env.npm_config_arch}`;
const outputBlobPath = `${baseDirPath}/cache/${npmConfigArch}`;
await mkdirp(outputBlobPath);
let mksnapshotBinPath
if (process.platform === 'win32') {
mksnapshotBinPath =
require.resolve(
path.join("electron-mksnapshot", "bin", "mksnapshot.exe")
);
} else {
mksnapshotBinPath =
require.resolve(
path.join("electron-mksnapshot", "bin", "mksnapshot")
);
}
mksnapshotBinPath = path.dirname(mksnapshotBinPath);
if (process.platform !== 'darwin') {
const mksnapshotBinPath = `${baseDirPath}/node_modules/electron-mksnapshot/bin`;
const matchingDirs = crossArchDirs.map((dir) => `${mksnapshotBinPath}/${dir}`).filter((dir) => fs.existsSync(dir));
for (const dir of matchingDirs) {
if (fs.existsSync(`${mksnapshotBinPath}/gen/v8/embedded.S`)) {
@ -50,7 +70,7 @@ async function main() {
console.log(`Generating startup blob in "${outputBlobPath}"`);
const res = childProcess.execFileSync(
path.resolve(__dirname, '..', 'node_modules', 'electron-mksnapshot', 'bin', 'mksnapshot' + (process.platform === 'win32' ? '.exe' : '')),
require.resolve(`electron-mksnapshot/bin/mksnapshot${process.platform === 'win32' ? '.exe' : ''}`),
[
'--startup-src=' + snapshotScriptPath,
'--startup-blob=' + startupBlobPath,

5
bin/notarize.js vendored
View file

@ -1,11 +1,12 @@
const { notarize } = require("@electron/notarize");
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== "darwin" || !process.env.APPLE_ID || !process.env.APPLE_PASSWORD) {
return;
}
const { notarize } = await import('@electron/notarize');
const appName = context.packager.appInfo.productFilename;
return await notarize({
appBundleId: "com.quineglobal.hyper",

View file

@ -1,8 +1,9 @@
import React, {forwardRef} from 'react';
import type {StyleSheetProps} from '../../typings/hyper';
import {useDevicePixelRatio} from 'use-device-pixel-ratio';
import type {StyleSheetProps} from '../../typings/hyper';
const StyleSheet = forwardRef<HTMLStyleElement, StyleSheetProps>((props, ref) => {
const {borderColor} = props;

View file

@ -1,5 +1,5 @@
{
"name": "hyper",
"name": "hyper-root",
"version": "4.0.0-q-canary.8",
"repository": "quine-global/hyper",
"engines": {
@ -92,7 +92,7 @@
"@babel/plugin-proposal-optional-chaining": "7.21.0",
"@babel/preset-react": "7.25.9",
"@babel/preset-typescript": "7.26.0",
"@electron/rebuild": "^3.7.1",
"@electron/rebuild": "^3.7.2",
"@types/args": "5.0.3",
"@types/async-retry": "1.4.9",
"@types/color": "3.0.6",
@ -115,10 +115,10 @@
"copy-webpack-plugin": "12.0.2",
"cpy-cli": "^5.0.0",
"cross-env": "7.0.3",
"electron": "34.5.1",
"electron": "38.6.0",
"electron-builder": "26.0.13",
"electron-link": "^0.6.0",
"electron-mksnapshot": "34.5.1",
"electron-mksnapshot": "38.6.0",
"electronmon": "^2.0.3",
"eslint": "8.57.0",
"eslint-config-prettier": "9.1.0",
@ -158,7 +158,7 @@
},
"resolutions": {
"@types/retry": "0.12.5",
"node-abi": "^3.67.0"
"node-abi": "^3.81.0"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

View file

@ -571,7 +571,7 @@
minimist "^1.2.6"
plist "^3.0.5"
"@electron/rebuild@3.7.2", "@electron/rebuild@^3.7.1":
"@electron/rebuild@3.7.2", "@electron/rebuild@^3.7.2":
version "3.7.2"
resolved "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.2.tgz#8d808b29159c50086d27a5dec72b40bf16b4b582"
integrity sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==
@ -1285,12 +1285,12 @@
dependencies:
undici-types "~5.26.4"
"@types/node@^20.9.0":
version "20.17.30"
resolved "https://registry.npmjs.org/@types/node/-/node-20.17.30.tgz#1d93f656d3b869dbef7b796568ac457606ba58d0"
integrity sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==
"@types/node@^22.7.7":
version "22.19.1"
resolved "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz#1188f1ddc9f46b4cc3aec76749050b4e1f459b7b"
integrity sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==
dependencies:
undici-types "~6.19.2"
undici-types "~6.21.0"
"@types/parse-path@^7.0.0":
version "7.0.3"
@ -3354,10 +3354,10 @@ electron-link@^0.6.0:
resolve "^1.19.0"
source-map "^0.7.3"
electron-mksnapshot@34.5.1:
version "34.5.1"
resolved "https://registry.npmjs.org/electron-mksnapshot/-/electron-mksnapshot-34.5.1.tgz#25fd5e935e9566d8ce157cb173643b0a9cf904e4"
integrity sha512-kD8VQLe/7vMw3ddAnJqcnseFQohTdZJSUgyoQpPwRa9fUf2Ko1sXBP9mriQjjw4Ho5SmKqaAz4rJMAUgsxf51Q==
electron-mksnapshot@38.6.0:
version "38.6.0"
resolved "https://registry.npmjs.org/electron-mksnapshot/-/electron-mksnapshot-38.6.0.tgz#ae9b20caa38087e157aba01607a85326d14d26d9"
integrity sha512-2/TpAa4iZ9roln5fTcAEsZrgaUSliglbWkyow/ae+yij6RHJO0dFzKihynSynLnEXgOPRQT6zrqKV53TTQOufA==
dependencies:
"@electron/get" "^2.0.1"
extract-zip "^2.0.0"
@ -3403,13 +3403,13 @@ electron-to-chromium@^1.5.73:
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.139.tgz#56ae7d42439e2967a54badbadaeb12f748987f37"
integrity sha512-GGnRYOTdN5LYpwbIr0rwP/ZHOQSvAF6TG0LSzp28uCBb9JiXHJGmaaKw29qjNJc5bGnnp6kXJqRnGMQoELwi5w==
electron@34.5.1:
version "34.5.1"
resolved "https://registry.npmjs.org/electron/-/electron-34.5.1.tgz#c7ce7b6f054eae6c7ef2d4ee933277db5bf069b3"
integrity sha512-z2Wm7QjhnJ5592fLITynj8UwIk1mBiT402mOakxSYiADrERIci3IOPk7xWHAFOMvt/eoG5RW16PPhgJiedZcGA==
electron@38.6.0:
version "38.6.0"
resolved "https://registry.npmjs.org/electron/-/electron-38.6.0.tgz#c862bff41d42776e307bf5cc92503dda23612339"
integrity sha512-68OFNxJlrEStA+t8k5atzf4frJddvRR1N1oalr49Ll8YZ0+0nEsDhw4UNhTCoZKTjSYcxFF/4rt+sco+OlnB3g==
dependencies:
"@electron/get" "^2.0.0"
"@types/node" "^20.9.0"
"@types/node" "^22.7.7"
extract-zip "^2.0.1"
electronmon@^2.0.3:
@ -6085,10 +6085,10 @@ nested-error-stacks@^2.1.1:
resolved "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5"
integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==
node-abi@^3.0.0, node-abi@^3.45.0, node-abi@^3.67.0:
version "3.74.0"
resolved "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz#5bfb4424264eaeb91432d2adb9da23c63a301ed0"
integrity sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==
node-abi@^3.0.0, node-abi@^3.45.0, node-abi@^3.81.0:
version "3.81.0"
resolved "https://registry.npmjs.org/node-abi/-/node-abi-3.81.0.tgz#176a80904b2d382f5e5d1abcfb44d681cf9105c5"
integrity sha512-I+SHs7vmUV9ooMDHVzFfUxFQRWeiBCGbI02+XB503WBS8RCDJl4vXSoAXzcnSWpzgItirp2EraDq7jQ2c7CIiA==
dependencies:
semver "^7.3.5"
@ -8274,7 +8274,7 @@ undici-types@~5.26.4:
resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
undici-types@~6.19.2, undici-types@~6.19.8:
undici-types@~6.19.8:
version "6.19.8"
resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==