Skip to content

Commit 2c57b8a

Browse files
authored
feat(loader): Allow to configure 'window.sentryOnLoad' (#58574)
Allow to configure a new `window.sentryOnLoad` callback, which can be defined before the Loader Script is loaded, thus allowing to streamline timing issues & prevent issues if e.g. the loader script was not loaded. tests added here getsentry/sentry-javascript#9331 Closes #58428
1 parent f84c774 commit 2c57b8a

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

scripts/build-js-loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ async function run() {
4242
const {code: minifiedBase} = await minify(base, {
4343
ecma: 5,
4444
mangle: {
45-
reserved: ['onLoad', 'forceLoad'],
45+
reserved: ['onLoad', 'forceLoad', 'sentryOnLoad'],
4646
},
4747
format: {
4848
ecma: 5,

src/sentry/templates/sentry/js-sdk-loader.js.tmpl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,20 @@
132132
}
133133
function setupSDK(SDK) {
134134
try {
135+
// If defined, we call window.sentryOnLoad first
136+
if (typeof _window.sentryOnLoad === 'function') {
137+
_window.sentryOnLoad();
138+
// Cleanup to allow garbage collection
139+
_window.sentryOnLoad = undefined;
140+
}
135141
// We have to make sure to call all callbacks first
136142
for (var i = 0; i < onLoadCallbacks.length; i++) {
137143
if (typeof onLoadCallbacks[i] === 'function') {
138144
onLoadCallbacks[i]();
139145
}
140146
}
147+
// Cleanup to allow garbage collection
148+
onLoadCallbacks.splice(0);
141149
// First call all inits from the queue
142150
for (var i = 0; i < queue.length; i++) {
143151
var item = queue[i];
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{% load sentry_helpers %}!function(n,e,r,t,i,o,a,c,u){for(var s=u,f=0;f<document.scripts.length;f++)if(document.scripts[f].src.indexOf(o)>-1){s&&"no"===document.scripts[f].getAttribute("data-lazy")&&(s=!1);break}var p=[];function l(n){return"e"in n}function d(n){return"p"in n}function _(n){return"f"in n}var v=[];function h(n){s&&(l(n)||d(n)||_(n)&&n.f.indexOf("capture")>-1||_(n)&&n.f.indexOf("showReportDialog")>-1)&&O(),v.push(n)}function y(){h({e:[].slice.call(arguments)})}function E(n){h({p:"reason"in n?n.reason:"detail"in n&&"reason"in n.detail?n.detail.reason:n})}function m(){try{n.SENTRY_SDK_SOURCE="loader";var e=n[i],o=e.init;e.init=function(i){n.removeEventListener(r,y),n.removeEventListener(t,E);var a=c;for(var u in i)Object.prototype.hasOwnProperty.call(i,u)&&(a[u]=i[u]);!function(n,e){var r=n.integrations||[];if(!Array.isArray(r))return;var t=r.map((function(n){return n.name}));n.tracesSampleRate&&-1===t.indexOf("BrowserTracing")&&r.push(new e.BrowserTracing);(n.replaysSessionSampleRate||n.replaysOnErrorSampleRate)&&-1===t.indexOf("Replay")&&r.push(new e.Replay);n.integrations=r}(a,e),o(a)},setTimeout((function(){return function(e){try{for(var r=0;r<p.length;r++)"function"==typeof p[r]&&p[r]();for(r=0;r<v.length;r++){_(o=v[r])&&"init"===o.f&&e.init.apply(e,o.a)}R()||e.init();var t=n.onerror,i=n.onunhandledrejection;for(r=0;r<v.length;r++){var o;if(_(o=v[r])){if("init"===o.f)continue;e[o.f].apply(e,o.a)}else l(o)&&t?t.apply(n,o.e):d(o)&&i&&i.apply(n,[o.p])}}catch(n){console.error(n)}}(e)}))}catch(n){console.error(n)}}var g=!1;function O(){if(!g){g=!0;var n=e.scripts[0],r=e.createElement("script");r.src=a,r.crossOrigin="anonymous",r.addEventListener("load",m,{once:!0,passive:!0}),n.parentNode.insertBefore(r,n)}}function R(){var e=n.__SENTRY__;return!(void 0===e||!e.hub||!e.hub.getClient())}n[i]=n[i]||{},n[i].onLoad=function(n){R()?n():p.push(n)},n[i].forceLoad=function(){setTimeout((function(){O()}))},["init","addBreadcrumb","captureMessage","captureException","captureEvent","configureScope","withScope","showReportDialog"].forEach((function(e){n[i][e]=function(){h({f:e,a:arguments})}})),n.addEventListener(r,y),n.addEventListener(t,E),s||setTimeout((function(){O()}))}(window,document,"error","unhandledrejection","Sentry",'{{ publicKey|safe }}','{{ jsSdkUrl|safe }}',{{ config|to_json|safe }},{{ isLazy|safe|lower }});
1+
{% load sentry_helpers %}!function(n,e,t,r,i,o,a,c,s){for(var u=s,f=0;f<document.scripts.length;f++)if(document.scripts[f].src.indexOf(o)>-1){u&&"no"===document.scripts[f].getAttribute("data-lazy")&&(u=!1);break}var p=[];function d(n){return"e"in n}function l(n){return"p"in n}function _(n){return"f"in n}var v=[];function y(n){u&&(d(n)||l(n)||_(n)&&n.f.indexOf("capture")>-1||_(n)&&n.f.indexOf("showReportDialog")>-1)&&L(),v.push(n)}function h(){y({e:[].slice.call(arguments)})}function E(n){y({p:"reason"in n?n.reason:"detail"in n&&"reason"in n.detail?n.detail.reason:n})}function O(){try{n.SENTRY_SDK_SOURCE="loader";var e=n[i],o=e.init;e.init=function(i){n.removeEventListener(t,h),n.removeEventListener(r,E);var a=c;for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(a[s]=i[s]);!function(n,e){var t=n.integrations||[];if(!Array.isArray(t))return;var r=t.map((function(n){return n.name}));n.tracesSampleRate&&-1===r.indexOf("BrowserTracing")&&t.push(new e.BrowserTracing);(n.replaysSessionSampleRate||n.replaysOnErrorSampleRate)&&-1===r.indexOf("Replay")&&t.push(new e.Replay);n.integrations=t}(a,e),o(a)},setTimeout((function(){return function(e){try{"function"==typeof n.sentryOnLoad&&(n.sentryOnLoad(),n.sentryOnLoad=void 0);for(var t=0;t<p.length;t++)"function"==typeof p[t]&&p[t]();p.splice(0);for(t=0;t<v.length;t++){_(o=v[t])&&"init"===o.f&&e.init.apply(e,o.a)}g()||e.init();var r=n.onerror,i=n.onunhandledrejection;for(t=0;t<v.length;t++){var o;if(_(o=v[t])){if("init"===o.f)continue;e[o.f].apply(e,o.a)}else d(o)&&r?r.apply(n,o.e):l(o)&&i&&i.apply(n,[o.p])}}catch(n){console.error(n)}}(e)}))}catch(n){console.error(n)}}var m=!1;function L(){if(!m){m=!0;var n=e.scripts[0],t=e.createElement("script");t.src=a,t.crossOrigin="anonymous",t.addEventListener("load",O,{once:!0,passive:!0}),n.parentNode.insertBefore(t,n)}}function g(){var e=n.__SENTRY__;return!(void 0===e||!e.hub||!e.hub.getClient())}n[i]=n[i]||{},n[i].onLoad=function(n){g()?n():p.push(n)},n[i].forceLoad=function(){setTimeout((function(){L()}))},["init","addBreadcrumb","captureMessage","captureException","captureEvent","configureScope","withScope","showReportDialog"].forEach((function(e){n[i][e]=function(){y({f:e,a:arguments})}})),n.addEventListener(t,h),n.addEventListener(r,E),u||setTimeout((function(){L()}))}(window,document,"error","unhandledrejection","Sentry",'{{ publicKey|safe }}','{{ jsSdkUrl|safe }}',{{ config|to_json|safe }},{{ isLazy|safe|lower }});

src/sentry/templates/sentry/js-sdk-loader.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,21 @@ declare const __LOADER__IS_LAZY__: any;
189189

190190
function setupSDK(SDK) {
191191
try {
192+
// If defined, we call window.sentryOnLoad first
193+
if (typeof _window.sentryOnLoad === 'function') {
194+
_window.sentryOnLoad();
195+
// Cleanup to allow garbage collection
196+
_window.sentryOnLoad = undefined;
197+
}
198+
192199
// We have to make sure to call all callbacks first
193200
for (let i = 0; i < onLoadCallbacks.length; i++) {
194201
if (typeof onLoadCallbacks[i] === 'function') {
195202
onLoadCallbacks[i]();
196203
}
197204
}
205+
// Cleanup to allow garbage collection
206+
onLoadCallbacks.splice(0);
198207

199208
// First call all inits from the queue
200209
for (let i = 0; i < queue.length; i++) {
@@ -284,7 +293,12 @@ declare const __LOADER__IS_LAZY__: any;
284293
}
285294
})(
286295
window as Window &
287-
typeof globalThis & {SENTRY_SDK_SOURCE?: string; Sentry?: any; __SENTRY__?: any},
296+
typeof globalThis & {
297+
SENTRY_SDK_SOURCE?: string;
298+
Sentry?: any;
299+
__SENTRY__?: any;
300+
sentryOnLoad?: () => void;
301+
},
288302
document,
289303
'error' as const,
290304
'unhandledrejection' as const,

0 commit comments

Comments
 (0)