Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@
},
"useConpty": {
"type": "boolean"
},
"useConptyDll": {
"description": "Windows only. If `true` (default), use the ConPTY that ships with `node-pty`\ninstead of the one built into Windows. The bundled ConPTY (1.23+) passes DCS\nsequences such as Sixel through to the terminal verbatim and reports Sixel\nsupport in its DA1 response; older inbox ConPTY versions filter them out,\nwhich breaks `imageSupport`.",
"type": "boolean"
}
},
"required": [
Expand Down
31 changes: 23 additions & 8 deletions app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,29 @@ async function installDevExtensions(isDev_: boolean) {
if (!isDev_) {
return [];
}
const {default: installer, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS} = await import('electron-devtools-installer');

const extensions = [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS];
const forceDownload = Boolean(process.env.UPGRADE_EXTENSIONS);

return Promise.all(
extensions.map((extension) => installer(extension, {forceDownload, loadExtensionOptions: {allowFileAccess: true}}))
);
// Installing devtools extensions is a dev-only convenience that depends on a
// remote download, and it can fail (e.g. the Chrome Web Store returning an
// error page instead of a .crx). This must never reject: the `ready` handler
// below creates the app windows inside the `.then()` of this promise, so a
// rejection here starts Hyper with no window at all.
try {
const {default: installer, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS} = await import('electron-devtools-installer');

const extensions = [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS];
const forceDownload = Boolean(process.env.UPGRADE_EXTENSIONS);

return await Promise.all(
extensions.map((extension) =>
installer(extension, {forceDownload, loadExtensionOptions: {allowFileAccess: true}}).catch((err: unknown) => {
console.warn('Skipping devtools extension:', err);
return undefined;
})
)
);
} catch (err) {
console.warn('Skipping devtools extensions:', err);
return [];
}
}

// eslint-disable-next-line @typescript-eslint/no-misused-promises
Expand Down
2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"lodash": "4.17.21",
"ms": "2.1.3",
"native-process-working-directory": "^1.0.2",
"node-pty": "1.0.0",
"node-pty": "1.1.0",
"os-locale": "5.0.0",
"parse-url": "8.1.0",
"queue": "6.0.2",
Expand Down
7 changes: 7 additions & 0 deletions app/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ try {
}

const useConpty = config.getConfig().useConpty;
// Defaults to true: the ConPTY bundled with node-pty (1.23+) passes DCS sequences
// such as Sixel through verbatim and advertises Sixel in its DA1 response, which
// the inbox ConPTY on many Windows builds does not. Set `useConptyDll: false` in
// the config to fall back to the Windows one.
const useConptyDll = config.getConfig().useConptyDll ?? true;

// Max duration to batch session data before sending it to the renderer process.
const BATCH_DURATION_MS = 16;
Expand Down Expand Up @@ -156,6 +161,8 @@ export default class Session extends EventEmitter {
options.useConpty = useConpty;
}

options.useConptyDll = useConptyDll;

try {
this.pty = spawn(shell, shellArgs, options);
} catch (_err) {
Expand Down
17 changes: 15 additions & 2 deletions bin/mk-snapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,22 @@ async function main() {
}

console.log(`Generating startup blob in "${outputBlobPath}"`);
const isWindows = process.platform === 'win32';
const mksnapshotPath = path.resolve(
__dirname,
'..',
'node_modules',
'.bin',
'mksnapshot' + (isWindows ? '.cmd' : '')
);
// Node >= 18.20.2 / 20.12.2 / 21.7.0 refuses to spawn .cmd and .bat files
// without `shell` (CVE-2024-27980), which makes execFileSync fail with
// EINVAL. On Windows, go through the shell and quote the arguments here.
const quote = (arg) => (isWindows ? `"${arg}"` : arg);
childProcess.execFileSync(
path.resolve(__dirname, '..', 'node_modules', '.bin', 'mksnapshot' + (process.platform === 'win32' ? '.cmd' : '')),
[snapshotScriptPath, '--output_dir', outputBlobPath]
quote(mksnapshotPath),
[snapshotScriptPath, '--output_dir', outputBlobPath].map(quote),
isWindows ? {shell: true} : {}
);
}

Expand Down
3 changes: 3 additions & 0 deletions electron-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
}
],
"artifactName": "${productName}-${version}-${arch}.${ext}",
"asarUnpack": [
"**/node_modules/node-pty/**"
],
"linux": {
"category": "TerminalEmulator",
"target": [
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"test:unit:watch": "pnpm run test:unit -- --watch",
"test:e2e": "ava --config ava-e2e.config.js",
"postinstall": "pnpm run v8-snapshot && webpack --config-name hyper-app && electron-builder install-app-deps && pnpm run rebuild-node-pty && cpy --cwd=target node_modules \"../../app/\" && husky install && pnpm run generate-schema",
"rebuild-node-pty": "electron-rebuild -f -o node-pty -m target",
"rebuild-node-pty": "electron-rebuild -f -o node-pty -m target && node target/node_modules/node-pty/scripts/post-install.js",
"dist": "pnpm run build && electron-builder",
"clean": "node ./bin/rimraf-standalone.js node_modules && node ./bin/rimraf-standalone.js ./app/node_modules && node ./bin/rimraf-standalone.js ./app/renderer",
"v8-snapshot": "cross-env npm_config_arch=x64 pnpm run v8-snapshot:arch && cross-env npm_config_arch=arm64 pnpm run v8-snapshot:arch",
Expand Down
8 changes: 8 additions & 0 deletions typings/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ type rootConfigOptions = {
/** choose either `'stable'` for receiving highly polished, or `'canary'` for less polished but more frequent updates */
updateChannel: 'stable' | 'canary';
useConpty?: boolean;
/**
* Windows only. If `true` (default), use the ConPTY that ships with `node-pty`
* instead of the one built into Windows. The bundled ConPTY (1.23+) passes DCS
* sequences such as Sixel through to the terminal verbatim and reports Sixel
* support in its DA1 response; older inbox ConPTY versions filter them out,
* which breaks `imageSupport`.
*/
useConptyDll?: boolean;
};

type profileConfigOptions = {
Expand Down