Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a8bf25
ref(node): use readline for context lines
JonasBa May 25, 2024
f134e4e
test(node): contextline tests
JonasBa May 26, 2024
b768d18
test(node): contextline tests
JonasBa May 26, 2024
a5929e4
ref(node): contextlines cache attempt
JonasBa May 28, 2024
d07afc5
ref(node) exclude other contextlines extensions
JonasBa Jun 9, 2024
4e3b7ce
test(node) fix contextlines test
JonasBa Jun 10, 2024
8bc27f9
fix scoped test
JonasBa Jun 10, 2024
811d12a
lint
JonasBa Jun 10, 2024
0fd4228
fix regexp danger warning
JonasBa Jun 10, 2024
72879e1
strict undefined check
JonasBa Jun 10, 2024
c1c5dbc
reshuffle order
JonasBa Jun 10, 2024
4cdae35
test adding error handler on input stream
JonasBa Jun 10, 2024
e183e86
lint
JonasBa Jun 10, 2024
fcdbdc2
fix duplicate reads on stream error
JonasBa Jun 11, 2024
d53ff2e
fix duplicate reads on stream error
JonasBa Jun 11, 2024
8ead438
add emplace
JonasBa Jun 11, 2024
e7ca32d
fix(node) last line is not picked up as it does not include \n
JonasBa Jun 11, 2024
c961478
ref(contexlines) use ordered startsWith instead of regexp and store c…
JonasBa Jun 12, 2024
2cb1ecf
ref(node) remove all but cache set snipline occurences
JonasBa Jun 12, 2024
34ece2d
fix(contextlines) update type assertions
JonasBa Jun 17, 2024
1ee5b96
fix(contextlines) use runtime checks instead
JonasBa Jun 17, 2024
23a115e
ref(node) fix types in tests
JonasBa Jun 17, 2024
7420b8b
test(node) fix wrong type assertion
JonasBa Jun 17, 2024
a8c6a91
ref(node) add limits to contextlines
JonasBa Jun 17, 2024
d89e244
test(node) add lineno and colno limits
JonasBa Jun 17, 2024
e82c510
fix typo
JonasBa Jun 17, 2024
79626c7
format
JonasBa Jun 17, 2024
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
17 changes: 16 additions & 1 deletion packages/node/src/integrations/contextlines.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ const LRU_FILE_CONTENTS_CACHE = new LRUMap<string, Record<number, string>>(10);
const LRU_FILE_CONTENTS_FS_READ_FAILED = new LRUMap<string, 1>(20);
const DEFAULT_LINES_OF_CONTEXT = 7;
const INTEGRATION_NAME = 'ContextLines';
// Determines the upper bound of lineno/colno that we will attempt to read. Large colno values are likely to be
// minified code while large lineno values are likely to be bundled code.
// Exported for testing purposes.
export const MAX_CONTEXTLINES_COLNO: number = 1000;
export const MAX_CONTEXTLINES_LINENO: number = 10000;

interface ContextLinesOptions {
/**
Expand DownExpand Up@@ -58,6 +63,15 @@ function shouldSkipContextLinesForFile(path: string): boolean {
if (path.startsWith('data:')) return true;
return false;
}

/**
* Determines if we should skip contextlines based off the max lineno and colno values.
*/
function shouldSkipContextLinesForFrame(frame: StackFrame): boolean {
if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
if (frame.colno !== undefined && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
return false;
}
/**
* Checks if we have all the contents that we need in the cache.
*/
Expand DownExpand Up@@ -216,7 +230,8 @@ async function addSourceContext(event: Event, contextLines: number): Promise<Eve
!frame ||
typeof filename !== 'string' ||
typeof frame.lineno !== 'number' ||
shouldSkipContextLinesForFile(filename)
shouldSkipContextLinesForFile(filename) ||
shouldSkipContextLinesForFrame(frame)
) {
continue;
}
Expand Down
41 changes: 40 additions & 1 deletion packages/node/test/integrations/contextlines.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import * as fs from 'node:fs';
import type { StackFrame } from '@sentry/types';
import { parseStackFrames } from '@sentry/utils';

import { _contextLinesIntegration, resetFileContentCache } from '../../src/integrations/contextlines';
import {
MAX_CONTEXTLINES_COLNO,
MAX_CONTEXTLINES_LINENO,
_contextLinesIntegration,
resetFileContentCache,
} from '../../src/integrations/contextlines';
import { defaultStackParser } from '../../src/sdk/api';
import { getError } from '../helpers/error';

Expand All@@ -22,6 +27,40 @@ describe('ContextLines', () => {
jest.clearAllMocks();
});

describe('limits', () => {
test(`colno above ${MAX_CONTEXTLINES_COLNO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: MAX_CONTEXTLINES_COLNO + 1,
filename: 'file:///var/task/index.js',
lineno: 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});

test(`lineno above ${MAX_CONTEXTLINES_LINENO}`, async () => {
expect.assertions(1);
const frames: StackFrame[] = [
{
colno: 1,
filename: 'file:///var/task/index.js',
lineno: MAX_CONTEXTLINES_LINENO + 1,
function: 'fxn1',
},
];

const readStreamSpy = jest.spyOn(fs, 'createReadStream');
await addContext(frames);
expect(readStreamSpy).not.toHaveBeenCalled();
});
});

describe('lru file cache', () => {
test('parseStack when file does not exist', async () => {
expect.assertions(4);
Expand Down