Skip to content

Commit dac0c97

Browse files
authored
don't create links when they won't be rendered (#248353)
dont create links when they wont be rendered
1 parent 6a98274 commit dac0c97

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

extensions/notebook-renderers/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function renderError(
190190
const minimalError = ctx.settings.minimalError && !!headerMessage?.length;
191191
outputElement.classList.add('traceback');
192192

193-
const { formattedStack, errorLocation } = formatStackTrace(err.stack);
193+
const { formattedStack, errorLocation } = formatStackTrace(err.stack, trustHtml);
194194

195195
const outputScrolling = !minimalError && scrollingEnabled(outputInfo, ctx.settings);
196196
const lineLimit = minimalError ? 1000 : ctx.settings.lineLimit;

extensions/notebook-renderers/src/stackTraceHelper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
export function formatStackTrace(stack: string): { formattedStack: string; errorLocation?: string } {
6+
export function formatStackTrace(stack: string, trustHtml: boolean): { formattedStack: string; errorLocation?: string } {
77
let cleaned: string;
88
// Ansi colors are described here:
99
// https://en.wikipedia.org/wiki/ANSI_escape_code under the SGR section
@@ -23,7 +23,7 @@ export function formatStackTrace(stack: string): { formattedStack: string; error
2323
return `${prefix}${num}${suffix}\n`;
2424
});
2525

26-
if (isIpythonStackTrace(cleaned)) {
26+
if (isIpythonStackTrace(cleaned) && trustHtml) {
2727
return linkifyStack(cleaned);
2828
}
2929

extensions/notebook-renderers/src/test/stackTraceHelper.test.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ suite('StackTraceHelper', () => {
1616
'@Main c:\\src\\test\\3\\otherlanguages\\julia.ipynb: 3\n' +
1717
'[2] top - level scope\n' +
1818
'@c:\\src\\test\\3\\otherlanguages\\julia.ipynb: 1; ';
19-
assert.equal(formatStackTrace(stack).formattedStack, stack);
19+
assert.equal(formatStackTrace(stack, true).formattedStack, stack);
2020
});
2121

2222
const formatSequence = /\u001b\[.+?m/g;
@@ -37,7 +37,7 @@ suite('StackTraceHelper', () => {
3737
'\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m\n\n' +
3838
'\u001b[1;31mException\u001b[0m\n:';
3939

40-
const { formattedStack, errorLocation } = formatStackTrace(stack);
40+
const { formattedStack, errorLocation } = formatStackTrace(stack, true);
4141
const cleanStack = stripAsciiFormatting(formattedStack);
4242
assert.ok(cleanStack.indexOf('Cell In[3], <a href=\'vscode-notebook-cell:?execution_count=3&line=2\'>line 2</a>') > 0, 'Missing line link in ' + cleanStack);
4343
assert.ok(cleanStack.indexOf('<a href=\'vscode-notebook-cell:?execution_count=3&line=2\'>2</a>') > 0, 'Missing frame link in ' + cleanStack);
@@ -56,13 +56,28 @@ suite('StackTraceHelper', () => {
5656
'\n' +
5757
'\u001b[31mTypeError\u001b[39m: unsupported operand type(s) for +: "NoneType" and "int"\n';
5858

59-
const { formattedStack, errorLocation } = formatStackTrace(stack);
59+
const { formattedStack, errorLocation } = formatStackTrace(stack, true);
6060
const cleanStack = stripAsciiFormatting(formattedStack);
6161
assert.ok(cleanStack.indexOf('Cell In[3], <a href=\'vscode-notebook-cell:?execution_count=3&line=2\'>line 2</a>') > 0, 'Missing line link in ' + cleanStack);
6262
assert.ok(cleanStack.indexOf('<a href=\'vscode-notebook-cell:?execution_count=3&line=2\'>2</a>') > 0, 'Missing frame link in ' + cleanStack);
6363
assert.equal(errorLocation, '<a href=\'vscode-notebook-cell:?execution_count=3&line=2\'>line 2</a>');
6464
});
6565

66+
test('Stack trace is not linkified when HTML is not trusted', () => {
67+
const stack =
68+
'\u001b[31m---------------------------------------------------------------------------\u001b[39m\n' +
69+
'\u001b[31mTypeError\u001b[39m Traceback (most recent call last)\n' +
70+
'\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 2\u001b[39m\n' +
71+
'\u001b[32m 1\u001b[39m x = firstItem((\u001b[32m1\u001b[39m, \u001b[32m2\u001b[39m, \u001b[32m3\u001b[39m, \u001b[32m5\u001b[39m))\n' +
72+
'\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m y = \u001b[43mx\u001b[49m\u001b[43m \u001b[49m\u001b[43m+\u001b[49m\u001b[43m \u001b[49m\u001b[32;43m1\u001b[39;49m\n' +
73+
'\u001b[32m 3\u001b[39m \u001b[38;5;28mprint\u001b[39m(y)\n' +
74+
'\n' +
75+
'\u001b[31mTypeError\u001b[39m: unsupported operand type(s) for +: "NoneType" and "int"\n';
76+
77+
const formattedLines = formatStackTrace(stack, false).formattedStack.split('\n');
78+
formattedLines.forEach(line => assert.ok(!/<a href=.*>/.test(line), 'line should not contain a link: ' + line));
79+
});
80+
6681
test('IPython stack line numbers are linkified for IPython 8.3', () => {
6782
// stack frames within functions do not list the line number, i.e.
6883
// 'Input In [1], in myfunc()' vs
@@ -85,7 +100,7 @@ suite('StackTraceHelper', () => {
85100
'\n' +
86101
'\u001b[1;31mException\u001b[0m:\n';
87102

88-
const { formattedStack } = formatStackTrace(stack);
103+
const { formattedStack } = formatStackTrace(stack, true);
89104
const formatted = stripAsciiFormatting(formattedStack);
90105
assert.ok(formatted.indexOf('Input <a href=\'vscode-notebook-cell:?execution_count=2\'>In [2]</a>, in <cell line: 5>') > 0, 'Missing cell link in ' + formatted);
91106
assert.ok(formatted.indexOf('Input <a href=\'vscode-notebook-cell:?execution_count=1\'>In [1]</a>, in myfunc()') > 0, 'Missing cell link in ' + formatted);
@@ -103,7 +118,7 @@ suite('StackTraceHelper', () => {
103118
'\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m\n\n' +
104119
'\u001b[1;31mException\u001b[0m\n:';
105120

106-
const formatted = formatStackTrace(stack).formattedStack;
121+
const formatted = formatStackTrace(stack, true).formattedStack;
107122
assert.ok(!/<a href=.*>\d<\/a>/.test(formatted), formatted);
108123
});
109124

@@ -118,7 +133,7 @@ suite('StackTraceHelper', () => {
118133
'a 1 print(\n' +
119134
' 1a print(\n';
120135

121-
const formattedLines = formatStackTrace(stack).formattedStack.split('\n');
136+
const formattedLines = formatStackTrace(stack, true).formattedStack.split('\n');
122137
assert.ok(/<a href='vscode-notebook-cell.*>/.test(formattedLines[0]), 'line should contain a link: ' + formattedLines[0]);
123138
formattedLines.slice(1).forEach(line => assert.ok(!/<a href=.*>/.test(line), 'line should not contain a link: ' + line));
124139
});
@@ -127,7 +142,7 @@ suite('StackTraceHelper', () => {
127142
const stack =
128143
'open\u001b[39;49m\u001b[43m(\u001b[49m\u001b[33;43m\'\u001b[39;49m\u001b[33;43minput.txt\u001b[39;49m\u001b[33;43m\'\u001b[39;49m\u001b[43m)\u001b[49m;';
129144

130-
const formattedLines = formatStackTrace(stack).formattedStack.split('\n');
145+
const formattedLines = formatStackTrace(stack, true).formattedStack.split('\n');
131146
assert.ok(!/4\d/.test(formattedLines[0]), 'should not contain background colors ' + formattedLines[0]);
132147
formattedLines.slice(1).forEach(line => assert.ok(!/<a href=.*>/.test(line), 'line should not contain a link: ' + line));
133148
});

0 commit comments

Comments
 (0)