-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Details
- Browser and browser version: all
- xterm.js version: 5.4.0
Steps to reproduce
- Define a terminal with a theme like:
const term = new Terminal({theme: {
background: 'black',
foreground: 'blue'
}});- Try to run it in a webpack served application with a
processfallback such as:
module.exports = {
resolve: {
fallback: {
process: require.resolve('process/browser')
}
}
}Se no error, and no warning but named colours no longer work.
This was introduced by #4851 which changed heuristic for detecting whether xterm.js is running in a browser or in a Node,js environment. It now simply looks for whether a process variable is defined, which makes isNode incorrectly true in many browser environments. These means that ctx is never defined here:
Lines 119 to 134 in 0658719
| export namespace css { | |
| let $ctx: CanvasRenderingContext2D | undefined; | |
| let $litmusColor: CanvasGradient | undefined; | |
| if (!isNode) { | |
| // This is guaranteed to run in the first window, so document should be correct | |
| const canvas = document.createElement('canvas'); | |
| canvas.width = 1; | |
| canvas.height = 1; | |
| const ctx = canvas.getContext('2d', { | |
| willReadFrequently: true | |
| }); | |
| if (ctx) { | |
| $ctx = ctx; | |
| $ctx.globalCompositeOperation = 'copy'; | |
| $litmusColor = $ctx.createLinearGradient(0, 0, 1, 1); | |
| } |
and then toColor short-circiuts due to lack of $ctx here:
Lines 184 to 187 in 0658719
| // Validate the context is available for canvas-based color parsing | |
| if (!$ctx || !$litmusColor) { | |
| throw new Error('css.toColor: Unsupported css format'); | |
| } |
Note that presence of process in webpack-served browser apps is a common concern - see the highly up-voted first comment on: https://stackoverflow.com/a/34550964/6646912
I found that many proposed solutions stop working if the code has been webpack'd, because webpack defines all kinds of
process,module,require, etc symbols.windowusually still works, unless of course you additionally also want to detect being run from a webworker, where there is nowindow.
Now process/browser shim is actually easy to detect because it has a .browser attribute and it's title is "browser". So, checking for: process.title !== 'browser' && !process.browser would already solve this for me.
However, something to consider is whether rather than checking for isNode in:
Lines 122 to 129 in 0658719
| if (!isNode) { | |
| // This is guaranteed to run in the first window, so document should be correct | |
| const canvas = document.createElement('canvas'); | |
| canvas.width = 1; | |
| canvas.height = 1; | |
| const ctx = canvas.getContext('2d', { | |
| willReadFrequently: true | |
| }); |
would it be better to just try-catch here? It (maybe naively) appears to me that what matters is not the fact of running on Node or not, but the fact of whether canvas context can be obtained or not.
What do you think is the best way forward?