From a3de1cfc6d108487d616ebff203805e74bc59301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ch=C5=82odnicki?= Date: Thu, 30 Jul 2020 09:25:06 +0200 Subject: [PATCH] fix(lazy): crash on iterating "delayedCalls" (#219) * fix: crash on iterating "delayedCalls" It looks like the code allowed "loadSentry()" to run more than once and the first run would unset "delayedCalls" causing the second run to crash on trying to iterate it. * Null-check vm as it might not exist --- lib/plugin.lazy.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/plugin.lazy.js b/lib/plugin.lazy.js index 59bc38d2..b74b7b3c 100644 --- a/lib/plugin.lazy.js +++ b/lib/plugin.lazy.js @@ -7,14 +7,16 @@ let SentryMock = {} <% } %> let sentryReadyResolve let loadInitiated = false +let loadCompleted = false <% if (options.lazy.injectMock) { %> -let loadCompleted = false const vueErrorHandler = VueLib.config.errorHandler VueLib.config.errorHandler = (error, vm, info) => { if (!loadCompleted) { - vm.$sentry.captureException(error) + if (vm) { + vm.$sentry.captureException(error) + } if (VueLib.util) { VueLib.util.warn(`Error in ${info}: "${error.toString()}"`, vm) @@ -42,7 +44,7 @@ export default function SentryPlugin (ctx, inject) { ctx.$sentry = SentryMock <% } %> - const loadSentryHook = () => !loadInitiated && loadSentry(ctx, inject) + const loadSentryHook = () => attemptLoadSentry(ctx, inject) <% if (options.lazy.injectLoadHook) { %> inject('sentryLoad', loadSentryHook) @@ -61,7 +63,11 @@ export default function SentryPlugin (ctx, inject) { ctx.$sentryReady = sentryReady } -async function loadSentry (ctx, inject) { +async function attemptLoadSentry(ctx, inject) { + if (loadInitiated) { + return + } + loadInitiated = true if (!window.<%= globals.nuxt %>) { @@ -69,7 +75,19 @@ async function loadSentry (ctx, inject) { // eslint-disable-next-line no-console console.warn(`$sentryLoad was called but window.<%= globals.nuxt %> is not available, delaying sentry loading until onNuxtReady callback. Do you really need to use lazy loading for Sentry?`) <% } %> + <% if (options.lazy.injectLoadHook) { %> window.<%= globals.readyCallback %>(() => loadSentry(ctx, inject)) + <% } else { %> + // Wait for onNuxtReady hook to trigger. + <% } %> + return + } + + await loadSentry(ctx, inject) +} + +async function loadSentry (ctx, inject) { + if (loadCompleted) { return } @@ -107,8 +125,8 @@ async function loadSentry (ctx, inject) { Sentry.init(config) <% } %> - <% if (options.lazy.injectMock) { %> loadCompleted = true + <% if (options.lazy.injectMock) { %> window.removeEventListener('error', SentryMock.captureException) delayedCalls.forEach(([methodName, args]) => Sentry[methodName].apply(Sentry, args))