Skip to content

Commit f68b3ec

Browse files
authored
fix: Node do not require window to build (getsentry#2007)
* fix: Node do not require window to build * fix: Remove unused lint rule * meta: Changelog
1 parent 7b81cf0 commit f68b3ec

File tree

7 files changed

+88
-86
lines changed

7 files changed

+88
-86
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- [utils] ref: Move `htmlTreeAsString` to `@sentry/browser`
6+
- [utils] ref: Remove `Window` typehint `getGlobalObject`
7+
38
## 5.0.6
49

510
- [utils]: Change how we use `utils` and expose `esm` build

packages/browser/src/integrations/helpers.ts

+78-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { captureException, getCurrentHub, withScope } from '@sentry/core';
22
import { Event as SentryEvent, Mechanism, WrappedFunction } from '@sentry/types';
3-
import { addExceptionTypeValue, htmlTreeAsString, normalize } from '@sentry/utils';
3+
import { addExceptionTypeValue, isString, normalize } from '@sentry/utils';
44

55
const debounceDuration: number = 1000;
66
let keypressTimeout: number | undefined;
@@ -181,7 +181,7 @@ export function breadcrumbEventHandler(eventName: string): (event: Event) => voi
181181
// can throw an exception in some circumstances.
182182
let target;
183183
try {
184-
target = htmlTreeAsString(event.target as Node);
184+
target = _htmlTreeAsString(event.target as Node);
185185
} catch (e) {
186186
target = '<unknown>';
187187
}
@@ -240,3 +240,79 @@ export function keypressEventHandler(): (event: Event) => void {
240240
}, debounceDuration) as any) as number;
241241
};
242242
}
243+
244+
/**
245+
* Given a child DOM element, returns a query-selector statement describing that
246+
* and its ancestors
247+
* e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
248+
* @returns generated DOM path
249+
*/
250+
function _htmlTreeAsString(elem: Node): string {
251+
let currentElem: Node | null = elem;
252+
const MAX_TRAVERSE_HEIGHT = 5;
253+
const MAX_OUTPUT_LEN = 80;
254+
const out = [];
255+
let height = 0;
256+
let len = 0;
257+
const separator = ' > ';
258+
const sepLength = separator.length;
259+
let nextStr;
260+
261+
while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {
262+
nextStr = _htmlElementAsString(currentElem as HTMLElement);
263+
// bail out if
264+
// - nextStr is the 'html' element
265+
// - the length of the string that would be created exceeds MAX_OUTPUT_LEN
266+
// (ignore this limit if we are on the first iteration)
267+
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)) {
268+
break;
269+
}
270+
271+
out.push(nextStr);
272+
273+
len += nextStr.length;
274+
currentElem = currentElem.parentNode;
275+
}
276+
277+
return out.reverse().join(separator);
278+
}
279+
280+
/**
281+
* Returns a simple, query-selector representation of a DOM element
282+
* e.g. [HTMLElement] => input#foo.btn[name=baz]
283+
* @returns generated DOM path
284+
*/
285+
function _htmlElementAsString(elem: HTMLElement): string {
286+
const out = [];
287+
let className;
288+
let classes;
289+
let key;
290+
let attr;
291+
let i;
292+
293+
if (!elem || !elem.tagName) {
294+
return '';
295+
}
296+
297+
out.push(elem.tagName.toLowerCase());
298+
if (elem.id) {
299+
out.push(`#${elem.id}`);
300+
}
301+
302+
className = elem.className;
303+
if (className && isString(className)) {
304+
classes = className.split(/\s+/);
305+
for (i = 0; i < classes.length; i++) {
306+
out.push(`.${classes[i]}`);
307+
}
308+
}
309+
const attrWhitelist = ['type', 'name', 'title', 'alt'];
310+
for (i = 0; i < attrWhitelist.length; i++) {
311+
key = attrWhitelist[i];
312+
attr = elem.getAttribute(key);
313+
if (attr) {
314+
out.push(`[${key}="${attr}"]`);
315+
}
316+
}
317+
return out.join('');
318+
}

packages/integrations/src/angular.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class Angular implements Integration {
4040
*/
4141
public constructor(options: { angular?: any } = {}) {
4242
// tslint:disable-next-line: no-unsafe-any
43-
this._angular = options.angular || getGlobalObject().angular;
43+
this._angular = options.angular || getGlobalObject<any>().angular;
4444
}
4545

4646
/**

packages/integrations/src/ember.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class Ember implements Integration {
2222
*/
2323
public constructor(options: { Ember?: any } = {}) {
2424
// tslint:disable-next-line: no-unsafe-any
25-
this._Ember = options.Ember || getGlobalObject().Ember;
25+
this._Ember = options.Ember || getGlobalObject<any>().Ember;
2626
}
2727

2828
/**

packages/integrations/src/reportingobserver.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export class ReportingObserver implements Integration {
8989

9090
this._getCurrentHub = getCurrentHub;
9191

92-
const observer = new (getGlobalObject()).ReportingObserver(this.handler.bind(this), {
92+
const observer = new (getGlobalObject<any>()).ReportingObserver(this.handler.bind(this), {
9393
buffered: true,
9494
types: this._options.types,
9595
});

packages/integrations/src/vue.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class Vue implements Integration {
3838
*/
3939
public constructor(options: { Vue?: any; attachProps?: boolean } = {}) {
4040
// tslint:disable-next-line: no-unsafe-any
41-
this._Vue = options.Vue || getGlobalObject().Vue;
41+
this._Vue = options.Vue || getGlobalObject<any>().Vue;
4242
if (options.attachProps === false) {
4343
this._attachProps = false;
4444
}

packages/utils/src/misc.ts

+1-80
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { Event, Mechanism, WrappedFunction } from '@sentry/types';
22

3-
import { isString } from './is';
4-
53
/** Internal */
64
interface SentryGlobal {
75
__SENTRY__: {
@@ -37,8 +35,7 @@ const fallbackGlobalObject = {};
3735
*
3836
* @returns Global scope object
3937
*/
40-
// tslint:disable:strict-type-predicates
41-
export function getGlobalObject<T extends Window | NodeJS.Global = any>(): T & SentryGlobal {
38+
export function getGlobalObject<T>(): T & SentryGlobal {
4239
return (isNodeEnv()
4340
? global
4441
: typeof window !== 'undefined'
@@ -99,82 +96,6 @@ export function uuid4(): string {
9996
});
10097
}
10198

102-
/**
103-
* Given a child DOM element, returns a query-selector statement describing that
104-
* and its ancestors
105-
* e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
106-
* @returns generated DOM path
107-
*/
108-
export function htmlTreeAsString(elem: Node): string {
109-
let currentElem: Node | null = elem;
110-
const MAX_TRAVERSE_HEIGHT = 5;
111-
const MAX_OUTPUT_LEN = 80;
112-
const out = [];
113-
let height = 0;
114-
let len = 0;
115-
const separator = ' > ';
116-
const sepLength = separator.length;
117-
let nextStr;
118-
119-
while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {
120-
nextStr = htmlElementAsString(currentElem as HTMLElement);
121-
// bail out if
122-
// - nextStr is the 'html' element
123-
// - the length of the string that would be created exceeds MAX_OUTPUT_LEN
124-
// (ignore this limit if we are on the first iteration)
125-
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)) {
126-
break;
127-
}
128-
129-
out.push(nextStr);
130-
131-
len += nextStr.length;
132-
currentElem = currentElem.parentNode;
133-
}
134-
135-
return out.reverse().join(separator);
136-
}
137-
138-
/**
139-
* Returns a simple, query-selector representation of a DOM element
140-
* e.g. [HTMLElement] => input#foo.btn[name=baz]
141-
* @returns generated DOM path
142-
*/
143-
export function htmlElementAsString(elem: HTMLElement): string {
144-
const out = [];
145-
let className;
146-
let classes;
147-
let key;
148-
let attr;
149-
let i;
150-
151-
if (!elem || !elem.tagName) {
152-
return '';
153-
}
154-
155-
out.push(elem.tagName.toLowerCase());
156-
if (elem.id) {
157-
out.push(`#${elem.id}`);
158-
}
159-
160-
className = elem.className;
161-
if (className && isString(className)) {
162-
classes = className.split(/\s+/);
163-
for (i = 0; i < classes.length; i++) {
164-
out.push(`.${classes[i]}`);
165-
}
166-
}
167-
const attrWhitelist = ['type', 'name', 'title', 'alt'];
168-
for (i = 0; i < attrWhitelist.length; i++) {
169-
key = attrWhitelist[i];
170-
attr = elem.getAttribute(key);
171-
if (attr) {
172-
out.push(`[${key}="${attr}"]`);
173-
}
174-
}
175-
return out.join('');
176-
}
177-
17899
/**
179100
* Parses string form of URL into an object
180101
* // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B

0 commit comments

Comments
 (0)