Skip to content

Commit

Permalink
Merge branch 'main' into fix/force-session-idle
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra committed Nov 28, 2024
2 parents 2b4515b + bd0ff25 commit c638dcb
Show file tree
Hide file tree
Showing 33 changed files with 1,030 additions and 159 deletions.
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
## 1.191.0 - 2024-11-28

- feat: different default and max idle period (#1558)

## 1.190.2 - 2024-11-27

- fix: patch to angular detection in rrweb (#1566)
- chore: fix changelog (#1564)

## 1.190.1 - 2024-11-27

- fix: catch errors detecting dialog state when recording (#1562)

## 1.190.0 - 2024-11-27

- feat: Add initial person info to cookie when using localPlusCookieStore (#1559)

## 1.189.1 - 2024-11-27

- feat: hog site functions (#1546)

## 1.189.0 - 2024-11-26

- feat: Add better npm import, and script entrypoint for customizations (#1550)

## 1.188.1 - 2024-11-26

- fix: safari support requires we don't use (#1553)
- fix: endless capturing /s/ (#1551)
- chore: make platform more specific (#1549)

## 1.188.0 - 2024-11-22

- fix(surveys): Process feature_flag_keys on Survey object (#1548)
- chore: sentry integration fixes (#1544)

## 1.187.2 - 2024-11-20

- fix: improve ES6 bundling (#1542)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthog-js",
"version": "1.187.2",
"version": "1.191.0",
"description": "Posthog-js allows you to automatically capture usage and send events to PostHog.",
"repository": "https://github.com/PostHog/posthog-js",
"author": "[email protected]",
Expand Down
61 changes: 48 additions & 13 deletions patches/@[email protected]
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
diff --git a/dist/record.js b/dist/record.js
index 46ec389fefb698243008b39db65470dbdf0a3857..891e1cf6439630d19e9b745ff428db438943a0b2 100644
index 46ec389fefb698243008b39db65470dbdf0a3857..70db907755d68b08232e25e1b255a974f56f3c65 100644
--- a/dist/record.js
+++ b/dist/record.js
@@ -26,6 +26,14 @@ const testableMethods$1 = {
@@ -26,6 +26,19 @@ const testableMethods$1 = {
Element: [],
MutationObserver: ["constructor"]
};
+const isFunction = (x) => typeof x === 'function';
+const isAngularZonePatchedFunction = (x) => {
+ if (!isFunction(x)) {
+ return false;
+ try {
+ if (!isFunction(x)) {
+ return false;
+ }
+ const prototypeKeys = Object.getOwnPropertyNames(x.prototype || {});
+ return prototypeKeys.some((key) => key.indexOf('__zone'));
+ } catch {
+ // we've seen some intermittent problems in Safari since introducing this check
+ return false
+ }
+ const prototypeKeys = Object.getOwnPropertyNames(x.prototype || {});
+ return prototypeKeys.some((key) => key.indexOf('__zone'));
+}
const untaintedBasePrototype$1 = {};
function getUntaintedPrototype$1(key) {
if (untaintedBasePrototype$1[key])
@@ -54,7 +62,7 @@ function getUntaintedPrototype$1(key) {
@@ -54,7 +67,7 @@ function getUntaintedPrototype$1(key) {
}
)
);
Expand All @@ -26,7 +31,20 @@ index 46ec389fefb698243008b39db65470dbdf0a3857..891e1cf6439630d19e9b745ff428db43
untaintedBasePrototype$1[key] = defaultObj.prototype;
return defaultObj.prototype;
}
@@ -246,6 +254,9 @@ function isCSSImportRule(rule2) {
@@ -65,10 +78,10 @@ function getUntaintedPrototype$1(key) {
if (!win) return defaultObj.prototype;
const untaintedObject = win[key].prototype;
document.body.removeChild(iframeEl);
- if (!untaintedObject) return defaultPrototype;
+ if (!untaintedObject) return defaultObj.prototype;
return untaintedBasePrototype$1[key] = untaintedObject;
} catch {
- return defaultPrototype;
+ return defaultObj.prototype;
}
}
const untaintedAccessorCache$1 = {};
@@ -246,6 +259,9 @@ function isCSSImportRule(rule2) {
function isCSSStyleRule(rule2) {
return "selectorText" in rule2;
}
Expand All @@ -36,7 +54,7 @@ index 46ec389fefb698243008b39db65470dbdf0a3857..891e1cf6439630d19e9b745ff428db43
class Mirror {
constructor() {
__publicField$1(this, "idNodeMap", /* @__PURE__ */ new Map());
@@ -809,9 +820,14 @@ function serializeElementNode(n2, options) {
@@ -809,9 +825,14 @@ function serializeElementNode(n2, options) {
}
}
if (tagName === "link" && inlineStylesheet) {
Expand All @@ -54,7 +72,24 @@ index 46ec389fefb698243008b39db65470dbdf0a3857..891e1cf6439630d19e9b745ff428db43
let cssText = null;
if (stylesheet) {
cssText = stringifyStylesheet(stylesheet);
@@ -1116,7300 +1132,227 @@ function serializeNodeWithId(n2, options) {
@@ -855,7 +876,15 @@ function serializeElementNode(n2, options) {
}
}
if (tagName === "dialog" && n2.open) {
- attributes.rr_open_mode = n2.matches("dialog:modal") ? "modal" : "non-modal";
+ try {
+ attributes.rr_open_mode = n2.matches("dialog:modal") ? "modal" : "non-modal";
+ } catch {
+ // likely this is safari not able to deal with the `:modal` selector
+ // we can't detect whether the dialog is modal or non-modal open, so have to guess
+ // hopefully this is only safari 15.4 and 15.5
+ attributes.rr_open_mode = "modal"
+ attributes.ph_rr_could_not_detect_modal = true
+ }
}
if (tagName === "canvas" && recordCanvas) {
if (n2.__context === "2d") {
@@ -1116,7300 +1145,227 @@ function serializeNodeWithId(n2, options) {
keepIframeSrcFn
};
if (serializedNode.type === NodeType$2.Element && serializedNode.tagName === "textarea" && serializedNode.attributes.value !== void 0) ;
Expand Down Expand Up @@ -7564,7 +7599,7 @@ index 46ec389fefb698243008b39db65470dbdf0a3857..891e1cf6439630d19e9b745ff428db43
class BaseRRNode {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
constructor(..._args) {
@@ -8507,7 +1450,7 @@ function getUntaintedPrototype(key) {
@@ -8507,7 +1463,7 @@ function getUntaintedPrototype(key) {
}
)
);
Expand All @@ -7573,7 +7608,7 @@ index 46ec389fefb698243008b39db65470dbdf0a3857..891e1cf6439630d19e9b745ff428db43
untaintedBasePrototype[key] = defaultObj.prototype;
return defaultObj.prototype;
}
@@ -11382,11 +4325,19 @@ class CanvasManager {
@@ -11382,11 +4338,19 @@ class CanvasManager {
let rafId;
const getCanvas = () => {
const matchedCanvas = [];
Expand All @@ -7598,7 +7633,7 @@ index 46ec389fefb698243008b39db65470dbdf0a3857..891e1cf6439630d19e9b745ff428db43
return matchedCanvas;
};
const takeCanvasSnapshots = (timestamp) => {
@@ -11407,13 +4358,20 @@ class CanvasManager {
@@ -11407,13 +4371,20 @@ class CanvasManager {
context.clear(context.COLOR_BUFFER_BIT);
}
}
Expand Down
2 changes: 1 addition & 1 deletion playground/nextjs/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { useActiveFeatureFlags, usePostHog } from 'posthog-js/react'
import { useEffect, useState } from 'react'
import { cookieConsentGiven, PERSON_PROCESSING_MODE } from '@/src/posthog'
import { setAllPersonProfilePropertiesAsPersonPropertiesForFlags } from 'posthog-js/lib/src/customizations/setAllPersonProfilePropertiesAsPersonPropertiesForFlags'
import { setAllPersonProfilePropertiesAsPersonPropertiesForFlags } from 'posthog-js/lib/src/customizations'
import { STORED_PERSON_PROPERTIES_KEY } from '../../../src/constants'

export default function Home() {
Expand Down
6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 0 additions & 31 deletions src/__tests__/decide.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Decide } from '../decide'
import { PostHogPersistence } from '../posthog-persistence'
import { RequestRouter } from '../utils/request-router'
import { expectScriptToExist, expectScriptToNotExist } from './helpers/script-utils'
import { PostHog } from '../posthog-core'
import { DecideResponse, PostHogConfig, Properties } from '../types'
import '../entrypoints/external-scripts-loader'
Expand Down Expand Up @@ -246,35 +245,5 @@ describe('Decide', () => {
expect(posthog._afterDecideResponse).toHaveBeenCalledWith(decideResponse)
expect(posthog.featureFlags.receivedFeatureFlags).not.toHaveBeenCalled()
})

it('runs site apps if opted in', () => {
posthog.config = {
api_host: 'https://test.com',
opt_in_site_apps: true,
persistence: 'memory',
} as PostHogConfig

subject({ siteApps: [{ id: 1, url: '/site_app/1/tokentoken/hash/' }] } as DecideResponse)

expectScriptToExist('https://test.com/site_app/1/tokentoken/hash/')
})

it('does not run site apps code if not opted in', () => {
;(window as any).POSTHOG_DEBUG = true
// don't technically need to run this but this test assumes opt_in_site_apps is false, let's make that explicit
posthog.config = {
api_host: 'https://test.com',
opt_in_site_apps: false,
persistence: 'memory',
} as unknown as PostHogConfig

subject({ siteApps: [{ id: 1, url: '/site_app/1/tokentoken/hash/' }] } as DecideResponse)

expect(console.error).toHaveBeenCalledWith(
'[PostHog.js]',
'PostHog site apps are disabled. Enable the "opt_in_site_apps" config to proceed.'
)
expectScriptToNotExist('https://test.com/site_app/1/tokentoken/hash/')
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ describe('LazyLoadedDeadClicksAutocapture', () => {
$dead_click_selection_changed_timeout: true,
$ce_version: 1,
$el_text: 'text',
$elements_chain: 'body:text="text"nth-child="2"nth-of-type="1"',
$elements: [
{
$el_text: 'text',
Expand Down Expand Up @@ -270,6 +271,7 @@ describe('LazyLoadedDeadClicksAutocapture', () => {
$dead_click_selection_changed_timeout: false,
$ce_version: 1,
$el_text: 'text',
$elements_chain: 'body:text="text"nth-child="2"nth-of-type="1"',
$elements: [
{
$el_text: 'text',
Expand Down Expand Up @@ -312,6 +314,7 @@ describe('LazyLoadedDeadClicksAutocapture', () => {
$dead_click_selection_changed_timeout: false,
$ce_version: 1,
$el_text: 'text',
$elements_chain: 'body:text="text"nth-child="2"nth-of-type="1"',
$elements: [
{
$el_text: 'text',
Expand Down Expand Up @@ -354,6 +357,7 @@ describe('LazyLoadedDeadClicksAutocapture', () => {
$dead_click_selection_changed_timeout: false,
$ce_version: 1,
$el_text: 'text',
$elements_chain: 'body:text="text"nth-child="2"nth-of-type="1"',
$elements: [
{
$el_text: 'text',
Expand Down
36 changes: 30 additions & 6 deletions src/__tests__/extensions/replay/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,34 +75,58 @@ describe('config', () => {
{
name: 'https://app.posthog.com/api/feature_flag/',
},
undefined,
],
[
{
name: 'https://app.posthog.com/s/',
name: 'https://app.posthog.com/s/?ip=1&ver=123',
},
undefined,
undefined,
],
[
{
name: 'https://app.posthog.com/e/',
name: 'https://app.posthog.com/e/?ip=1&ver=123',
},
undefined,
undefined,
],
[
{
name: 'https://app.posthog.com/i/v0/e/',
name: 'https://app.posthog.com/i/v0/e/?ip=1&ver=123',
},
undefined,
undefined,
],
[
{
// even an imaginary future world of rust session replay capture
name: 'https://app.posthog.com/i/v0/s/',
name: 'https://app.posthog.com/i/v0/s/?ip=1&ver=123',
},
undefined,
undefined,
],
])('ignores ingestion paths', (capturedRequest, expected) => {
const networkOptions = buildNetworkRequestOptions(defaultConfig(), {})
[
{
// using a relative path as a reverse proxy api host
name: 'https://app.posthog.com/ingest/s/?ip=1&ver=123',
},
undefined,
'/ingest',
],
[
{
// using a reverse proxy with a path
name: 'https://app.posthog.com/ingest/s/?ip=1&ver=123',
},
undefined,
'https://app.posthog.com/ingest',
],
])('ignores ingestion paths', (capturedRequest, expected, apiHost?: string) => {
const networkOptions = buildNetworkRequestOptions(
{ ...defaultConfig(), api_host: apiHost || 'https://us.posthog.com' },
{}
)
const x = networkOptions.maskRequestFn!(capturedRequest as CapturedNetworkRequest)
expect(x).toEqual(expected)
})
Expand Down
18 changes: 15 additions & 3 deletions src/__tests__/extensions/replay/sessionrecording.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ describe('SessionRecording', () => {
const postHogPersistence = new PostHogPersistence(config)
postHogPersistence.clear()

sessionManager = new SessionIdManager(config, postHogPersistence, sessionIdGeneratorMock, windowIdGeneratorMock)
sessionManager = new SessionIdManager(
{ config, persistence: postHogPersistence, register: jest.fn() } as unknown as PostHog,
sessionIdGeneratorMock,
windowIdGeneratorMock
)

// add capture hook returns an unsubscribe function
removeCaptureHookMock = jest.fn()
Expand Down Expand Up @@ -1130,7 +1134,11 @@ describe('SessionRecording', () => {
let unsubscribeCallback: () => void

beforeEach(() => {
sessionManager = new SessionIdManager(config, new PostHogPersistence(config))
sessionManager = new SessionIdManager({
config,
persistence: new PostHogPersistence(config),
register: jest.fn(),
} as unknown as PostHog)
posthog.sessionManager = sessionManager

mockCallback = jest.fn()
Expand Down Expand Up @@ -1216,7 +1224,11 @@ describe('SessionRecording', () => {

describe('with a real session id manager', () => {
beforeEach(() => {
sessionManager = new SessionIdManager(config, new PostHogPersistence(config))
sessionManager = new SessionIdManager({
config,
persistence: new PostHogPersistence(config),
register: jest.fn(),
} as unknown as PostHog)
posthog.sessionManager = sessionManager

sessionRecording.startIfEnabledOrStop()
Expand Down
Loading

0 comments on commit c638dcb

Please sign in to comment.