@myinterview/widget-react 1.1.23-development-94da5c1 → 1.1.23-development-ff49dbb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -5794,7 +5794,7 @@ function getEventForEnvelopeItem(item, type) {
5794
5794
  return Array.isArray(item) ? (item )[1] : undefined;
5795
5795
  }
5796
5796
 
5797
- const SDK_VERSION = '7.51.2';
5797
+ const SDK_VERSION = '7.52.1';
5798
5798
 
5799
5799
  let originalFunctionToString;
5800
5800
 
@@ -5975,8 +5975,9 @@ function _getPossibleEventMessages(event) {
5975
5975
  return [event.message];
5976
5976
  }
5977
5977
  if (event.exception) {
5978
+ const { values } = event.exception;
5978
5979
  try {
5979
- const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
5980
+ const { type = '', value = '' } = (values && values[values.length - 1]) || {};
5980
5981
  return [`${value}`, `${type}: ${value}`];
5981
5982
  } catch (oO) {
5982
5983
  (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
@@ -11522,6 +11523,475 @@ record.takeFullSnapshot = (isCheckout) => {
11522
11523
  };
11523
11524
  record.mirror = mirror;
11524
11525
 
11526
+ /**
11527
+ * Create a breadcrumb for a replay.
11528
+ */
11529
+ function createBreadcrumb(
11530
+ breadcrumb,
11531
+ ) {
11532
+ return {
11533
+ timestamp: Date.now() / 1000,
11534
+ type: 'default',
11535
+ ...breadcrumb,
11536
+ };
11537
+ }
11538
+
11539
+ var NodeType;
11540
+ (function (NodeType) {
11541
+ NodeType[NodeType["Document"] = 0] = "Document";
11542
+ NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
11543
+ NodeType[NodeType["Element"] = 2] = "Element";
11544
+ NodeType[NodeType["Text"] = 3] = "Text";
11545
+ NodeType[NodeType["CDATA"] = 4] = "CDATA";
11546
+ NodeType[NodeType["Comment"] = 5] = "Comment";
11547
+ })(NodeType || (NodeType = {}));
11548
+
11549
+ /**
11550
+ * Converts a timestamp to ms, if it was in s, or keeps it as ms.
11551
+ */
11552
+ function timestampToMs(timestamp) {
11553
+ const isMs = timestamp > 9999999999;
11554
+ return isMs ? timestamp : timestamp * 1000;
11555
+ }
11556
+
11557
+ /**
11558
+ * Add an event to the event buffer.
11559
+ * `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
11560
+ */
11561
+ async function addEvent(
11562
+ replay,
11563
+ event,
11564
+ isCheckout,
11565
+ ) {
11566
+ if (!replay.eventBuffer) {
11567
+ // This implies that `_isEnabled` is false
11568
+ return null;
11569
+ }
11570
+
11571
+ if (replay.isPaused()) {
11572
+ // Do not add to event buffer when recording is paused
11573
+ return null;
11574
+ }
11575
+
11576
+ const timestampInMs = timestampToMs(event.timestamp);
11577
+
11578
+ // Throw out events that happen more than 5 minutes ago. This can happen if
11579
+ // page has been left open and idle for a long period of time and user
11580
+ // comes back to trigger a new session. The performance entries rely on
11581
+ // `performance.timeOrigin`, which is when the page first opened.
11582
+ if (timestampInMs + replay.timeouts.sessionIdlePause < Date.now()) {
11583
+ return null;
11584
+ }
11585
+
11586
+ try {
11587
+ if (isCheckout) {
11588
+ replay.eventBuffer.clear();
11589
+ }
11590
+
11591
+ return await replay.eventBuffer.addEvent(event);
11592
+ } catch (error) {
11593
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
11594
+ await replay.stop('addEvent');
11595
+
11596
+ const client = getCurrentHub().getClient();
11597
+
11598
+ if (client) {
11599
+ client.recordDroppedEvent('internal_sdk_error', 'replay');
11600
+ }
11601
+ }
11602
+ }
11603
+
11604
+ /**
11605
+ * Add a breadcrumb event to replay.
11606
+ */
11607
+ function addBreadcrumbEvent(replay, breadcrumb) {
11608
+ if (breadcrumb.category === 'sentry.transaction') {
11609
+ return;
11610
+ }
11611
+
11612
+ if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
11613
+ replay.triggerUserActivity();
11614
+ } else {
11615
+ replay.checkAndHandleExpiredSession();
11616
+ }
11617
+
11618
+ replay.addUpdate(() => {
11619
+ void addEvent(replay, {
11620
+ type: EventType$1.Custom,
11621
+ // TODO: We were converting from ms to seconds for breadcrumbs, spans,
11622
+ // but maybe we should just keep them as milliseconds
11623
+ timestamp: (breadcrumb.timestamp || 0) * 1000,
11624
+ data: {
11625
+ tag: 'breadcrumb',
11626
+ // normalize to max. 10 depth and 1_000 properties per object
11627
+ payload: normalize(breadcrumb, 10, 1000),
11628
+ },
11629
+ });
11630
+
11631
+ // Do not flush after console log messages
11632
+ return breadcrumb.category === 'console';
11633
+ });
11634
+ }
11635
+
11636
+ /**
11637
+ * Detect a slow click on a button/a tag,
11638
+ * and potentially create a corresponding breadcrumb.
11639
+ */
11640
+ function detectSlowClick(
11641
+ replay,
11642
+ config,
11643
+ clickBreadcrumb,
11644
+ node,
11645
+ ) {
11646
+ if (ignoreElement(node, config)) {
11647
+ return;
11648
+ }
11649
+
11650
+ /*
11651
+ We consider a slow click a click on a button/a, which does not trigger one of:
11652
+ - DOM mutation
11653
+ - Scroll (within 100ms)
11654
+ Within the given threshold time.
11655
+ After time timeout time, we stop listening and mark it as a slow click anyhow.
11656
+ */
11657
+
11658
+ let cleanup = () => {
11659
+ // replaced further down
11660
+ };
11661
+
11662
+ // After timeout time, def. consider this a slow click, and stop watching for mutations
11663
+ const timeout = setTimeout(() => {
11664
+ handleSlowClick(replay, clickBreadcrumb, config.timeout, 'timeout');
11665
+ cleanup();
11666
+ }, config.timeout);
11667
+
11668
+ const mutationHandler = () => {
11669
+ maybeHandleSlowClick(replay, clickBreadcrumb, config.threshold, config.timeout, 'mutation');
11670
+ cleanup();
11671
+ };
11672
+
11673
+ const scrollHandler = () => {
11674
+ maybeHandleSlowClick(replay, clickBreadcrumb, config.scrollTimeout, config.timeout, 'scroll');
11675
+ cleanup();
11676
+ };
11677
+
11678
+ const obs = new MutationObserver(mutationHandler);
11679
+
11680
+ obs.observe(WINDOW.document.documentElement, {
11681
+ attributes: true,
11682
+ characterData: true,
11683
+ childList: true,
11684
+ subtree: true,
11685
+ });
11686
+
11687
+ WINDOW.addEventListener('scroll', scrollHandler);
11688
+
11689
+ // Stop listening to scroll timeouts early
11690
+ const scrollTimeout = setTimeout(() => {
11691
+ WINDOW.removeEventListener('scroll', scrollHandler);
11692
+ }, config.scrollTimeout);
11693
+
11694
+ cleanup = () => {
11695
+ clearTimeout(timeout);
11696
+ clearTimeout(scrollTimeout);
11697
+ obs.disconnect();
11698
+ WINDOW.removeEventListener('scroll', scrollHandler);
11699
+ };
11700
+ }
11701
+
11702
+ function maybeHandleSlowClick(
11703
+ replay,
11704
+ clickBreadcrumb,
11705
+ threshold,
11706
+ timeout,
11707
+ endReason,
11708
+ ) {
11709
+ const now = Date.now();
11710
+ const timeAfterClickMs = now - clickBreadcrumb.timestamp * 1000;
11711
+
11712
+ if (timeAfterClickMs > threshold) {
11713
+ handleSlowClick(replay, clickBreadcrumb, Math.min(timeAfterClickMs, timeout), endReason);
11714
+ return true;
11715
+ }
11716
+
11717
+ return false;
11718
+ }
11719
+
11720
+ function handleSlowClick(
11721
+ replay,
11722
+ clickBreadcrumb,
11723
+ timeAfterClickMs,
11724
+ endReason,
11725
+ ) {
11726
+ const breadcrumb = {
11727
+ message: clickBreadcrumb.message,
11728
+ timestamp: clickBreadcrumb.timestamp,
11729
+ category: 'ui.slowClickDetected',
11730
+ data: {
11731
+ ...clickBreadcrumb.data,
11732
+ url: WINDOW.location.href,
11733
+ // TODO FN: add parametrized route, when possible
11734
+ timeAfterClickMs,
11735
+ endReason,
11736
+ },
11737
+ };
11738
+
11739
+ addBreadcrumbEvent(replay, breadcrumb);
11740
+ }
11741
+
11742
+ const SLOW_CLICK_IGNORE_TAGS = ['SELECT', 'OPTION'];
11743
+
11744
+ function ignoreElement(node, config) {
11745
+ // If <input> tag, we only want to consider input[type='submit'] & input[type='button']
11746
+ if (node.tagName === 'INPUT' && !['submit', 'button'].includes(node.getAttribute('type') || '')) {
11747
+ return true;
11748
+ }
11749
+
11750
+ if (SLOW_CLICK_IGNORE_TAGS.includes(node.tagName)) {
11751
+ return true;
11752
+ }
11753
+
11754
+ // If <a> tag, detect special variants that may not lead to an action
11755
+ // If target !== _self, we may open the link somewhere else, which would lead to no action
11756
+ // Also, when downloading a file, we may not leave the page, but still not trigger an action
11757
+ if (
11758
+ node.tagName === 'A' &&
11759
+ (node.hasAttribute('download') || (node.hasAttribute('target') && node.getAttribute('target') !== '_self'))
11760
+ ) {
11761
+ return true;
11762
+ }
11763
+
11764
+ if (config.ignoreSelector && node.matches(config.ignoreSelector)) {
11765
+ return true;
11766
+ }
11767
+
11768
+ return false;
11769
+ }
11770
+
11771
+ // Note that these are the serialized attributes and not attributes directly on
11772
+ // the DOM Node. Attributes we are interested in:
11773
+ const ATTRIBUTES_TO_RECORD = new Set([
11774
+ 'id',
11775
+ 'class',
11776
+ 'aria-label',
11777
+ 'role',
11778
+ 'name',
11779
+ 'alt',
11780
+ 'title',
11781
+ 'data-test-id',
11782
+ 'data-testid',
11783
+ ]);
11784
+
11785
+ /**
11786
+ * Inclusion list of attributes that we want to record from the DOM element
11787
+ */
11788
+ function getAttributesToRecord(attributes) {
11789
+ const obj = {};
11790
+ for (const key in attributes) {
11791
+ if (ATTRIBUTES_TO_RECORD.has(key)) {
11792
+ let normalizedKey = key;
11793
+
11794
+ if (key === 'data-testid' || key === 'data-test-id') {
11795
+ normalizedKey = 'testId';
11796
+ }
11797
+
11798
+ obj[normalizedKey] = attributes[key];
11799
+ }
11800
+ }
11801
+
11802
+ return obj;
11803
+ }
11804
+
11805
+ const handleDomListener = (
11806
+ replay,
11807
+ ) => {
11808
+ const slowClickExperiment = replay.getOptions()._experiments.slowClicks;
11809
+
11810
+ const slowClickConfig = slowClickExperiment
11811
+ ? {
11812
+ threshold: slowClickExperiment.threshold,
11813
+ timeout: slowClickExperiment.timeout,
11814
+ scrollTimeout: slowClickExperiment.scrollTimeout,
11815
+ ignoreSelector: slowClickExperiment.ignoreSelectors ? slowClickExperiment.ignoreSelectors.join(',') : '',
11816
+ }
11817
+ : undefined;
11818
+
11819
+ return (handlerData) => {
11820
+ if (!replay.isEnabled()) {
11821
+ return;
11822
+ }
11823
+
11824
+ const result = handleDom(handlerData);
11825
+
11826
+ if (!result) {
11827
+ return;
11828
+ }
11829
+
11830
+ const isClick = handlerData.name === 'click';
11831
+ const event = isClick && (handlerData.event );
11832
+ // Ignore clicks if ctrl/alt/meta keys are held down as they alter behavior of clicks (e.g. open in new tab)
11833
+ if (isClick && slowClickConfig && event && !event.altKey && !event.metaKey && !event.ctrlKey) {
11834
+ detectSlowClick(
11835
+ replay,
11836
+ slowClickConfig,
11837
+ result ,
11838
+ getClickTargetNode(handlerData.event) ,
11839
+ );
11840
+ }
11841
+
11842
+ addBreadcrumbEvent(replay, result);
11843
+ };
11844
+ };
11845
+
11846
+ /** Get the base DOM breadcrumb. */
11847
+ function getBaseDomBreadcrumb(target, message) {
11848
+ // `__sn` property is the serialized node created by rrweb
11849
+ const serializedNode = target && isRrwebNode(target) && target.__sn.type === NodeType.Element ? target.__sn : null;
11850
+
11851
+ return {
11852
+ message,
11853
+ data: serializedNode
11854
+ ? {
11855
+ nodeId: serializedNode.id,
11856
+ node: {
11857
+ id: serializedNode.id,
11858
+ tagName: serializedNode.tagName,
11859
+ textContent: target
11860
+ ? Array.from(target.childNodes)
11861
+ .map(
11862
+ (node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
11863
+ )
11864
+ .filter(Boolean) // filter out empty values
11865
+ .map(text => (text ).trim())
11866
+ .join('')
11867
+ : '',
11868
+ attributes: getAttributesToRecord(serializedNode.attributes),
11869
+ },
11870
+ }
11871
+ : {},
11872
+ };
11873
+ }
11874
+
11875
+ /**
11876
+ * An event handler to react to DOM events.
11877
+ * Exported for tests.
11878
+ */
11879
+ function handleDom(handlerData) {
11880
+ const { target, message } = getDomTarget(handlerData);
11881
+
11882
+ return createBreadcrumb({
11883
+ category: `ui.${handlerData.name}`,
11884
+ ...getBaseDomBreadcrumb(target, message),
11885
+ });
11886
+ }
11887
+
11888
+ function getDomTarget(handlerData) {
11889
+ const isClick = handlerData.name === 'click';
11890
+
11891
+ let message;
11892
+ let target = null;
11893
+
11894
+ // Accessing event.target can throw (see getsentry/raven-js#838, #768)
11895
+ try {
11896
+ target = isClick ? getClickTargetNode(handlerData.event) : getTargetNode(handlerData.event);
11897
+ message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
11898
+ } catch (e) {
11899
+ message = '<unknown>';
11900
+ }
11901
+
11902
+ return { target, message };
11903
+ }
11904
+
11905
+ function isRrwebNode(node) {
11906
+ return '__sn' in node;
11907
+ }
11908
+
11909
+ function getTargetNode(event) {
11910
+ if (isEventWithTarget(event)) {
11911
+ return event.target ;
11912
+ }
11913
+
11914
+ return event;
11915
+ }
11916
+
11917
+ const INTERACTIVE_SELECTOR = 'button,a';
11918
+
11919
+ // For clicks, we check if the target is inside of a button or link
11920
+ // If so, we use this as the target instead
11921
+ // This is useful because if you click on the image in <button><img></button>,
11922
+ // The target will be the image, not the button, which we don't want here
11923
+ function getClickTargetNode(event) {
11924
+ const target = getTargetNode(event);
11925
+
11926
+ if (!target || !(target instanceof Element)) {
11927
+ return target;
11928
+ }
11929
+
11930
+ const closestInteractive = target.closest(INTERACTIVE_SELECTOR);
11931
+ return closestInteractive || target;
11932
+ }
11933
+
11934
+ function isEventWithTarget(event) {
11935
+ return typeof event === 'object' && !!event && 'target' in event;
11936
+ }
11937
+
11938
+ /** Handle keyboard events & create breadcrumbs. */
11939
+ function handleKeyboardEvent(replay, event) {
11940
+ if (!replay.isEnabled()) {
11941
+ return;
11942
+ }
11943
+
11944
+ replay.triggerUserActivity();
11945
+
11946
+ const breadcrumb = getKeyboardBreadcrumb(event);
11947
+
11948
+ if (!breadcrumb) {
11949
+ return;
11950
+ }
11951
+
11952
+ addBreadcrumbEvent(replay, breadcrumb);
11953
+ }
11954
+
11955
+ /** exported only for tests */
11956
+ function getKeyboardBreadcrumb(event) {
11957
+ const { metaKey, shiftKey, ctrlKey, altKey, key, target } = event;
11958
+
11959
+ // never capture for input fields
11960
+ if (!target || isInputElement(target )) {
11961
+ return null;
11962
+ }
11963
+
11964
+ // Note: We do not consider shift here, as that means "uppercase"
11965
+ const hasModifierKey = metaKey || ctrlKey || altKey;
11966
+ const isCharacterKey = key.length === 1; // other keys like Escape, Tab, etc have a longer length
11967
+
11968
+ // Do not capture breadcrumb if only a word key is pressed
11969
+ // This could leak e.g. user input
11970
+ if (!hasModifierKey && isCharacterKey) {
11971
+ return null;
11972
+ }
11973
+
11974
+ const message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
11975
+ const baseBreadcrumb = getBaseDomBreadcrumb(target , message);
11976
+
11977
+ return createBreadcrumb({
11978
+ category: 'ui.keyDown',
11979
+ message,
11980
+ data: {
11981
+ ...baseBreadcrumb.data,
11982
+ metaKey,
11983
+ shiftKey,
11984
+ ctrlKey,
11985
+ altKey,
11986
+ key,
11987
+ },
11988
+ });
11989
+ }
11990
+
11991
+ function isInputElement(target) {
11992
+ return target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;
11993
+ }
11994
+
11525
11995
  const NAVIGATION_ENTRY_KEYS = [
11526
11996
  'name',
11527
11997
  'type',
@@ -11659,14 +12129,6 @@ function t(t){let e=t.length;for(;--e>=0;)t[e]=0}const e=new Uint8Array([0,0,0,0
11659
12129
 
11660
12130
  function e(){const e=new Blob([r]);return URL.createObjectURL(e)}
11661
12131
 
11662
- /**
11663
- * Converts a timestamp to ms, if it was in s, or keeps it as ms.
11664
- */
11665
- function timestampToMs(timestamp) {
11666
- const isMs = timestamp > 9999999999;
11667
- return isMs ? timestamp : timestamp * 1000;
11668
- }
11669
-
11670
12132
  /**
11671
12133
  * A basic event buffer that does not do any compression.
11672
12134
  * Used as fallback if the compression worker cannot be loaded or is disabled.
@@ -12244,53 +12706,6 @@ function getSession({
12244
12706
  return { type: 'new', session: newSession };
12245
12707
  }
12246
12708
 
12247
- /**
12248
- * Add an event to the event buffer.
12249
- * `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
12250
- */
12251
- async function addEvent(
12252
- replay,
12253
- event,
12254
- isCheckout,
12255
- ) {
12256
- if (!replay.eventBuffer) {
12257
- // This implies that `_isEnabled` is false
12258
- return null;
12259
- }
12260
-
12261
- if (replay.isPaused()) {
12262
- // Do not add to event buffer when recording is paused
12263
- return null;
12264
- }
12265
-
12266
- const timestampInMs = timestampToMs(event.timestamp);
12267
-
12268
- // Throw out events that happen more than 5 minutes ago. This can happen if
12269
- // page has been left open and idle for a long period of time and user
12270
- // comes back to trigger a new session. The performance entries rely on
12271
- // `performance.timeOrigin`, which is when the page first opened.
12272
- if (timestampInMs + replay.timeouts.sessionIdlePause < Date.now()) {
12273
- return null;
12274
- }
12275
-
12276
- try {
12277
- if (isCheckout) {
12278
- replay.eventBuffer.clear();
12279
- }
12280
-
12281
- return await replay.eventBuffer.addEvent(event);
12282
- } catch (error) {
12283
- (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
12284
- await replay.stop('addEvent');
12285
-
12286
- const client = getCurrentHub().getClient();
12287
-
12288
- if (client) {
12289
- client.recordDroppedEvent('internal_sdk_error', 'replay');
12290
- }
12291
- }
12292
- }
12293
-
12294
12709
  /** If the event is an error event */
12295
12710
  function isErrorEvent(event) {
12296
12711
  return !event.type;
@@ -12376,187 +12791,6 @@ function isBaseTransportSend() {
12376
12791
  );
12377
12792
  }
12378
12793
 
12379
- var NodeType;
12380
- (function (NodeType) {
12381
- NodeType[NodeType["Document"] = 0] = "Document";
12382
- NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
12383
- NodeType[NodeType["Element"] = 2] = "Element";
12384
- NodeType[NodeType["Text"] = 3] = "Text";
12385
- NodeType[NodeType["CDATA"] = 4] = "CDATA";
12386
- NodeType[NodeType["Comment"] = 5] = "Comment";
12387
- })(NodeType || (NodeType = {}));
12388
-
12389
- /**
12390
- * Create a breadcrumb for a replay.
12391
- */
12392
- function createBreadcrumb(
12393
- breadcrumb,
12394
- ) {
12395
- return {
12396
- timestamp: Date.now() / 1000,
12397
- type: 'default',
12398
- ...breadcrumb,
12399
- };
12400
- }
12401
-
12402
- /**
12403
- * Add a breadcrumb event to replay.
12404
- */
12405
- function addBreadcrumbEvent(replay, breadcrumb) {
12406
- if (breadcrumb.category === 'sentry.transaction') {
12407
- return;
12408
- }
12409
-
12410
- if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
12411
- replay.triggerUserActivity();
12412
- } else {
12413
- replay.checkAndHandleExpiredSession();
12414
- }
12415
-
12416
- replay.addUpdate(() => {
12417
- void addEvent(replay, {
12418
- type: EventType$1.Custom,
12419
- // TODO: We were converting from ms to seconds for breadcrumbs, spans,
12420
- // but maybe we should just keep them as milliseconds
12421
- timestamp: (breadcrumb.timestamp || 0) * 1000,
12422
- data: {
12423
- tag: 'breadcrumb',
12424
- // normalize to max. 10 depth and 1_000 properties per object
12425
- payload: normalize(breadcrumb, 10, 1000),
12426
- },
12427
- });
12428
-
12429
- // Do not flush after console log messages
12430
- return breadcrumb.category === 'console';
12431
- });
12432
- }
12433
-
12434
- // Note that these are the serialized attributes and not attributes directly on
12435
- // the DOM Node. Attributes we are interested in:
12436
- const ATTRIBUTES_TO_RECORD = new Set([
12437
- 'id',
12438
- 'class',
12439
- 'aria-label',
12440
- 'role',
12441
- 'name',
12442
- 'alt',
12443
- 'title',
12444
- 'data-test-id',
12445
- 'data-testid',
12446
- ]);
12447
-
12448
- /**
12449
- * Inclusion list of attributes that we want to record from the DOM element
12450
- */
12451
- function getAttributesToRecord(attributes) {
12452
- const obj = {};
12453
- for (const key in attributes) {
12454
- if (ATTRIBUTES_TO_RECORD.has(key)) {
12455
- let normalizedKey = key;
12456
-
12457
- if (key === 'data-testid' || key === 'data-test-id') {
12458
- normalizedKey = 'testId';
12459
- }
12460
-
12461
- obj[normalizedKey] = attributes[key];
12462
- }
12463
- }
12464
-
12465
- return obj;
12466
- }
12467
-
12468
- const handleDomListener =
12469
- (replay) =>
12470
- (handlerData) => {
12471
- if (!replay.isEnabled()) {
12472
- return;
12473
- }
12474
-
12475
- const result = handleDom(handlerData);
12476
-
12477
- if (!result) {
12478
- return;
12479
- }
12480
-
12481
- addBreadcrumbEvent(replay, result);
12482
- };
12483
-
12484
- /**
12485
- * An event handler to react to DOM events.
12486
- * Exported for tests only.
12487
- */
12488
- function handleDom(handlerData) {
12489
- let target;
12490
- let targetNode;
12491
-
12492
- const isClick = handlerData.name === 'click';
12493
-
12494
- // Accessing event.target can throw (see getsentry/raven-js#838, #768)
12495
- try {
12496
- targetNode = isClick ? getClickTargetNode(handlerData.event) : getTargetNode(handlerData.event);
12497
- target = htmlTreeAsString(targetNode, { maxStringLength: 200 });
12498
- } catch (e) {
12499
- target = '<unknown>';
12500
- }
12501
-
12502
- // `__sn` property is the serialized node created by rrweb
12503
- const serializedNode =
12504
- targetNode && '__sn' in targetNode && targetNode.__sn.type === NodeType.Element ? targetNode.__sn : null;
12505
-
12506
- return createBreadcrumb({
12507
- category: `ui.${handlerData.name}`,
12508
- message: target,
12509
- data: serializedNode
12510
- ? {
12511
- nodeId: serializedNode.id,
12512
- node: {
12513
- id: serializedNode.id,
12514
- tagName: serializedNode.tagName,
12515
- textContent: targetNode
12516
- ? Array.from(targetNode.childNodes)
12517
- .map(
12518
- (node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
12519
- )
12520
- .filter(Boolean) // filter out empty values
12521
- .map(text => (text ).trim())
12522
- .join('')
12523
- : '',
12524
- attributes: getAttributesToRecord(serializedNode.attributes),
12525
- },
12526
- }
12527
- : {},
12528
- });
12529
- }
12530
-
12531
- function getTargetNode(event) {
12532
- if (isEventWithTarget(event)) {
12533
- return event.target;
12534
- }
12535
-
12536
- return event;
12537
- }
12538
-
12539
- const INTERACTIVE_SELECTOR = 'button,a';
12540
-
12541
- // For clicks, we check if the target is inside of a button or link
12542
- // If so, we use this as the target instead
12543
- // This is useful because if you click on the image in <button><img></button>,
12544
- // The target will be the image, not the button, which we don't want here
12545
- function getClickTargetNode(event) {
12546
- const target = getTargetNode(event);
12547
-
12548
- if (!target || !(target instanceof Element)) {
12549
- return target;
12550
- }
12551
-
12552
- const closestInteractive = target.closest(INTERACTIVE_SELECTOR);
12553
- return closestInteractive || target;
12554
- }
12555
-
12556
- function isEventWithTarget(event) {
12557
- return !!(event ).target;
12558
- }
12559
-
12560
12794
  /**
12561
12795
  * Returns true if we think the given event is an error originating inside of rrweb.
12562
12796
  */
@@ -13474,7 +13708,32 @@ function _strIsProbablyJson(str) {
13474
13708
 
13475
13709
  /** Match an URL against a list of strings/Regex. */
13476
13710
  function urlMatches(url, urls) {
13477
- return stringMatchesSomePattern(url, urls);
13711
+ const fullUrl = getFullUrl(url);
13712
+
13713
+ return stringMatchesSomePattern(fullUrl, urls);
13714
+ }
13715
+
13716
+ /** exported for tests */
13717
+ function getFullUrl(url, baseURI = WINDOW.document.baseURI) {
13718
+ // Short circuit for common cases:
13719
+ if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith(WINDOW.location.origin)) {
13720
+ return url;
13721
+ }
13722
+ const fixedUrl = new URL(url, baseURI);
13723
+
13724
+ // If these do not match, we are not dealing with a relative URL, so just return it
13725
+ if (fixedUrl.origin !== new URL(baseURI).origin) {
13726
+ return url;
13727
+ }
13728
+
13729
+ const fullUrl = fixedUrl.href;
13730
+
13731
+ // Remove trailing slashes, if they don't match the original URL
13732
+ if (!url.endsWith('/') && fullUrl.endsWith('/')) {
13733
+ return fullUrl.slice(0, -1);
13734
+ }
13735
+
13736
+ return fullUrl;
13478
13737
  }
13479
13738
 
13480
13739
  /**
@@ -15399,8 +15658,8 @@ class ReplayContainer {
15399
15658
  };}
15400
15659
 
15401
15660
  /** Ensure page remains active when a key is pressed. */
15402
- __init16() {this._handleKeyboardEvent = () => {
15403
- this.triggerUserActivity();
15661
+ __init16() {this._handleKeyboardEvent = (event) => {
15662
+ handleKeyboardEvent(this, event);
15404
15663
  };}
15405
15664
 
15406
15665
  /**
@@ -30069,7 +30328,12 @@ const DEVICE = {
30069
30328
  PLATFORM: PLATFORMS_OPTIONS.find((p) => { var _a, _b; return (_b = (_a = platform.os) === null || _a === void 0 ? void 0 : _a.family) === null || _b === void 0 ? void 0 : _b.toUpperCase().includes(p === 'MACBOOK' ? 'OS X' : p); }) || 'WINDOWS',
30070
30329
  BROWSER: BROWSERS_OPTIONS.find((b) => { var _a; return (_a = platform.name) === null || _a === void 0 ? void 0 : _a.toUpperCase().includes(b); }) || 'CHROME',
30071
30330
  };
30072
- const isPortrait = () => !screen.orientation.type.startsWith('landscape');
30331
+ const isPortrait = () => {
30332
+ if (typeof window.matchMedia !== 'undefined') {
30333
+ return window.matchMedia('(orientation: portrait)').matches;
30334
+ }
30335
+ return window.innerHeight > window.innerWidth;
30336
+ };
30073
30337
  const iPhoneModels = [
30074
30338
  { pixelRatio: 2, width: 640, height: 1136, model: 'iPhone SE (1st generation)' },
30075
30339
  { pixelRatio: 2, width: 750, height: 1334, model: 'iPhone SE (2nd generation)/6/6S/7/8' },