From ad95b567a1e55aa93b65fdacc77802f7fdbbbd87 Mon Sep 17 00:00:00 2001 From: LaunchDarklyReleaseBot <86431345+LaunchDarklyReleaseBot@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:48:04 -0800 Subject: [PATCH] prepare 3.1.0 release (#265) * add ability to alter URL in events * Update browserPlatform definition to detect when an EventSource polyfill is available and has published that it supports setting the method used for the stream. When this is the case, the platform publishes that it supports using REPORT with EventSource and will provide the polyfill implementation if the SDK attempts a EventSource connection with the method set to REPORT. * Fix initial linter warnings. * Fix another linter warning. * fix a broken readme link (#202) * removing a stray character in the readme * fix stream reconnect logic and add stream connection logging * linter * assume logger always exists, as we do in other components * fix and simplify how the logger object is passed around * make it so eventUrlTransformer actually does something * linter * copy flags object to prevent subtle update problem in Electron * additional fix + test * make bootstrapped flags available immediately * Refactor some of the EventSource constructor selection logic. * Change browserPlatform.js to check config options when determining EventSource implementation to use. Added tests for EventSource factory in browserPlatform.js * Deal with linter. * change how supported options are detected in EventSource polyfill * fix broken homepage attributes (#209) * improve bad initialization messages (#210) * improve bad initialization messages * remove the spaces * fixing a broken link in a logged message (#212) * add jsdelivr attribute to js packages (#213) * adding an option to disable the camel-casing of flag keys (#214) * adding an option disabling the camel-casing of flag keys * update comment * update comment * fix linter errors * address pr feedback * updated readme * [ch45487] useCamelCaseFlagKeys option (#215) * Initial commit * Update initLDClient.ts * PR fixes. Added prettier. * Update withLDProvider.test.tsx * Fixed lint errors. Added test for useCamelCase false on server changes. * Removed prettier. * Re-added prettier * Update yarn.lock * Update prettier and lock files. * Fixed more linting issues. * fix a typo * use persistent anonymous user logic by default in react sdk (#216) * use persistent anonymous user logic by default in react sdk * added a comment * minor test change * missed a line * remove React package from monorepo * make link text match link * improve log format and add configurable prefix * fix test * linter * deprecate samplingInterval * linter * improve log message for stream connection failures (#221) * improve log message for stream connection failures * update the reconnection warning so that it only displays for the first set of each reconnection attempts * also test that the original put is getting called * updating tests * updating tests * Revert "updating tests" This reverts commit 84163cdf8b5af6a6e969d777b946a8a2973919ed. * better abstraction * minor change * updating the js-common readme to mention client-side node (#222) * remove common package, no more monorepo * add Releaser metadata * npm audit fix * unify Rollup config * migrate new demo code to new package structure * moved example folder * syntax fix in demo * fix directory name * fix linting * use spread operator instead of Object.assign * don't close client on beforeunload, but do flush events * typo * clarify test postconditions * misc test app improvements for testing beforeunload handler * rm unused yarn.lock * rm typedoc dependency, don't commit installation of it during release * fix paths * fix file copying logic * pr template * revert * fix programmatically reported version string * upgrade Typescript to avoid Typedoc incompatibility * Revert "upgrade Typescript to avoid Typedoc incompatibility" This reverts commit 34d9a0fc404992758e7b36df323c610e2accb471. * update Babel, Jest, Rollup * remove old releaser (#229) * remove unused Rollup plugins, update dependencies * use new config validation mechanism in js-sdk-common 3.x * add image-loading event delivery logic factored out of js-sdk-common * enable diagnostic events in JS SDK * lint * fix tests * use common 3.0.0-beta2 * use 3.1.0-beta3, fix property name * lint * use js-sdk-common 3.1.0 * use js-sdk-common 3.1.1 for event payload ID fix * use js-sdk-common 3.1.2 and loosen our other dependency * fix license * use js-sdk-common 3.2.0-beta1 * SDK name should be js-client-sdk * misc fixes * use js-sdk-common 3.2.0 * use js-sdk-common 3.2.0 * standardize linting * use js-sdk-common 3.2.1 * use js-sdk-common 3.2.2 * update package-lock * update js-sdk-common dependency for initialization error bugfix * update js-sdk-common for content type bugfix; update some dev dependencies * remove unsafe usage of hasOwnProperty * use js-sdk-common 3.2.5 * resolve security vulnerability in acorn dependency (#240) * update js-sdk-common to get console logging IE bugfix * update js-sdk-common for duplicate diagnostic event fix * update js-sdk-common for TS decl fix, improve TS compilation test (#243) * bump to 3.2.9 to get startsWith fix (#244) * add option to disable sync event flush (#245) * update js-sdk-common + some dev dependencies * No longer remove non-section hash in substring and regex matching * linting * the linting target to run in CI is "lint:all", not "lint" * new js-common-sdk version (#249) * resolve node-notifier vulnerability by updating jest dep (#250) * adding contextKind to goal events, bumping js-common to get alias function (#251) * pin typedoc to unblock our releases (#252) * Removed the guides link * add inlineUsersToEvents to TypeScript defs by updating js-sdk-common * Update common JS SDK library to use fixes for debug event generation issues. * Update package lock. * use Releaser v2 config + newer CI image (#256) * Updated readme headers (#258) * don't log a warning about custom goal being unknown * lint + comment * Release js-client-sdk with the header transformation change * Updates docs link * bump js-sdk-common version for better localstorage error handling * Update launchdarkly-js-sdk-common for JSON error handling fix (sc-142333) * update lockfile * add basicLogger export * Update common for application tags support. (#265) * Re-remove package-lock.json and add it to the .gitignore. (#266) * Switch to 5.0 of the SDK common. * Use a combination of dependencies that is compatible. (#269) * Use a combination of dependencies that is compatible. (#269) (#270) * Update js-sdk-common to 3.7.0 (#271) * Update node version used during release. (#272) * Update common to 3.8.1 (#273) * Update common version for jitter and backoff. (#274) * Update typedoc and make associated documentation changes. (#275) * Update to prerelease package. (#276) * Update release config to use node 14. * Update typedoc and make associated documentation changes. (#275) (#277) * Update to pre-release common 5.0.0-alpha.2 * Update typings.d.ts (#278) Co-authored-by: Yusinto Ngadiman * Update to js-sdk-common 5.0.0-alpha.3 * [sc-177790] Replaced getUser with getContext (#279) * Replaced getUser with getContext * Remove contextKind * Update GoalManager.js Co-authored-by: Yusinto Ngadiman * Update GoalManager.js (#280) * Switch to 5.0 of the SDK common. * Use a combination of dependencies that is compatible. (#269) * Update to prerelease package. (#276) * Update release config to use node 14. * Update typedoc and make associated documentation changes. (#275) (#277) * Update to pre-release common 5.0.0-alpha.2 * Update typings.d.ts (#278) Co-authored-by: Yusinto Ngadiman * Update to js-sdk-common 5.0.0-alpha.3 * [sc-177790] Replaced getUser with getContext (#279) * Replaced getUser with getContext * Remove contextKind * Update GoalManager.js Co-authored-by: Yusinto Ngadiman * Update GoalManager.js Co-authored-by: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Co-authored-by: Yusinto Ngadiman * Update GoalManager.js (#281) Co-authored-by: Yusinto Ngadiman * Update SDK common version. (#282) * Update release metadata. * Refactor to use page visibility instead of unload/beforeunload. (#267) * Upgrade JS SDK common to 5.0.1 for documentation fixes. (#283) * Correcting documentation on visibility handler. Co-authored-by: Eli Bishop Co-authored-by: LaunchDarklyCI Co-authored-by: Gavin Whelan Co-authored-by: Ben Woskow <48036130+bwoskow-ld@users.noreply.github.com> Co-authored-by: Ben Woskow Co-authored-by: Zach Davis Co-authored-by: Elliot <35050275+Apache-HB@users.noreply.github.com> Co-authored-by: LaunchDarklyReleaseBot Co-authored-by: Louis Chan Co-authored-by: Louis Chan <91093020+louis-launchdarkly@users.noreply.github.com> Co-authored-by: Ember Stevens Co-authored-by: ember-stevens <79482775+ember-stevens@users.noreply.github.com> Co-authored-by: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Co-authored-by: Yusinto Ngadiman Co-authored-by: Yusinto Ngadiman --- package.json | 2 +- src/__tests__/LDClient-test.js | 16 +++++++++++----- src/browserPlatform.js | 2 +- src/index.js | 33 +++++++++++++++++++++++---------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 42e0ae3b..40696e96 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ }, "dependencies": { "escape-string-regexp": "^4.0.0", - "launchdarkly-js-sdk-common": "5.0.0" + "launchdarkly-js-sdk-common": "5.0.1" }, "repository": { "type": "git", diff --git a/src/__tests__/LDClient-test.js b/src/__tests__/LDClient-test.js index 0c195e52..2d0554e0 100644 --- a/src/__tests__/LDClient-test.js +++ b/src/__tests__/LDClient-test.js @@ -173,12 +173,18 @@ describe('LDClient', () => { expect(server.requests[1].async).toBe(true); }); - async function setupClientAndTriggerUnload() { + async function setupClientAndTriggerPageHide() { const config = { bootstrap: {}, flushInterval: 100000, fetchGoals: false, diagnosticOptOut: true }; const client = LDClient.initialize(envName, user, config); await client.waitForInitialization(); - window.dispatchEvent(new window.Event('beforeunload')); + Object.defineProperty(document, 'visibilityState', { + configurable: true, + get: function () { + return 'hidden'; + }, + }); + document.dispatchEvent(new window.Event('visibilitychange')); return client; } @@ -188,7 +194,7 @@ describe('LDClient', () => { it('in ' + desc, async () => { window.navigator.__defineGetter__('userAgent', () => ua); - await setupClientAndTriggerUnload(); + await setupClientAndTriggerPageHide(); expect(server.requests.length).toEqual(2); // ignore first request because it's just a side effect of calling browserPlatform.httpAllowsPost() @@ -211,7 +217,7 @@ describe('LDClient', () => { it('in ' + desc, async () => { window.navigator.__defineGetter__('userAgent', () => ua); - const client = await setupClientAndTriggerUnload(); + const client = await setupClientAndTriggerPageHide(); expect(server.requests.length).toEqual(2); // ignore first request because it's just a side effect of calling browserPlatform.httpAllowsPost() expect(server.requests[1].async).toBe(false); // events @@ -237,7 +243,7 @@ describe('LDClient', () => { it('in ' + desc, async () => { window.navigator.__defineGetter__('userAgent', () => ua); - await setupClientAndTriggerUnload(); + await setupClientAndTriggerPageHide(); window.dispatchEvent(new window.Event('beforeunload')); diff --git a/src/browserPlatform.js b/src/browserPlatform.js index fb2dc42f..cc2dad7c 100644 --- a/src/browserPlatform.js +++ b/src/browserPlatform.js @@ -5,7 +5,7 @@ export default function makeBrowserPlatform(options) { userAgentHeaderName: 'X-LaunchDarkly-User-Agent', }; - ret.synchronousFlush = false; // this will be set to true by index.js if the page is closing + ret.synchronousFlush = false; // this will be set to true by index.js if the page is hidden // XMLHttpRequest may not exist if we're running in a server-side rendering context if (window.XMLHttpRequest) { diff --git a/src/index.js b/src/index.js index e4084c84..2ac4556c 100644 --- a/src/index.js +++ b/src/index.js @@ -43,20 +43,33 @@ export function initialize(env, user, options = {}) { clientVars.start(); } - // We'll attempt to flush events via synchronous HTTP if the page is about to close, to improve - // the chance that the events will really be delivered, although synchronous requests aren't - // supported in all browsers (see httpRequest.js). We will do it for both beforeunload and - // unload, in case any events got generated by code that ran in another beforeunload handler. - // We will not call client.close() though, since in the case of a beforeunload event the page - // might not actually get closed, and with an unload event we know everything will get discarded - // anyway. - const syncFlushHandler = () => { + const syncFlush = () => { + // Synchronous events are not available in all browsers, but where they + // are we should attempt to use them. This increases the chance of the events + // being delivered. platform.synchronousFlush = true; client.flush().catch(() => {}); platform.synchronousFlush = false; }; - window.addEventListener('beforeunload', syncFlushHandler); - window.addEventListener('unload', syncFlushHandler); + + // When the visibility of the page changes to hidden we want to flush any pending events. + // + // This is handled with visibility, instead of beforeunload/unload + // because those events are not compatible with the bfcache and are unlikely + // to be called in many situations. For more information see: https://developer.chrome.com/blog/page-lifecycle-api/ + // + // Redundancy is included by using both the visibilitychange handler as well as + // pagehide, because different browsers, and versions have different bugs with each. + // This also may provide more opportunity for the events to get flushed. + // + const handleVisibilityChange = () => { + if (document.visibilityState === 'hidden') { + syncFlush(); + } + }; + + document.addEventListener('visibilitychange', handleVisibilityChange); + window.addEventListener('pagehide', syncFlush); return client; }