Skip to content

fix(vue): expose countlyGlobal on Vue prototype (template render crash in dev build)#7658

Merged
ar2rsawseen merged 1 commit into
masterfrom
fix/vue-countlyglobal-prototype
Jun 4, 2026
Merged

fix(vue): expose countlyGlobal on Vue prototype (template render crash in dev build)#7658
ar2rsawseen merged 1 commit into
masterfrom
fix/vue-countlyglobal-prototype

Conversation

@ar2rsawseen

Copy link
Copy Markdown
Member

Symptom

With the dev/warning Vue build (frontend.production=false), any page whose Vue template references countlyGlobal throws during render and breaks the page:

[Vue warn]: Property or method "countlyGlobal" is not defined on the instance but referenced during render
TypeError: Cannot read properties of undefined (reading 'path')

(In countly-platform this crashed the Drill page on every query — the loading/thinking avatar template uses countlyGlobal.path.)

Root cause

countlyGlobal is a window-level global. Vue 2's render proxy (present in the dev/warning build) does not fall through to window for identifiers in template expressions, so countlyGlobal resolves to undefined and undefined.path throws. It only "works" in the minified build, where with(this) falls through to window.countlyGlobal. So any countlyGlobal.* in a .html template binding (:src=, :href=, {{ }}) is a latent crash. The defensive (countlyGlobal.path || '') form doesn't help — countlyGlobal.path is evaluated before || ''. (JS-file uses in countly.models.js/countly.views.js are fine — this only affects template expressions.)

Fix (single, central)

In frontend/express/public/javascripts/countly/vue/core.js, right after Vue.prototype.$route = new BackboneRouteAdapter();, expose it on the prototype via a getter (so it always reflects the current window.countlyGlobal):

Object.defineProperty(Vue.prototype, "countlyGlobal", {
    configurable: true,
    get: function() { return window.countlyGlobal; }
});

This covers every dashboard template referencing countlyGlobal across core and all plugins. Enterprise plugins need no separate change — they render inside this same dashboard Vue instance. No per-component data/computed shims. Confirmed Vue.prototype.countlyGlobal wasn't already defined.

Verify

  • node --check on core.js passes; eslint clean.
  • With frontend.production=false, a page using a countlyGlobal.* template binding (Drill run-query, push compose preview, views config) renders with no [Vue warn]/render error and resolves asset URLs.
  • For production/minified mode the bundled /min/ assets are rebuilt by CI (grunt dist-all); only the source change is committed here.

🤖 Generated with Claude Code

countlyGlobal is a window-level global, but Vue 2's render proxy (present
in the dev/warning build, frontend.production=false) does not fall through
to window for identifiers used in template expressions. So a bare
countlyGlobal.* in a .html template binding resolves to undefined and
throws "Cannot read properties of undefined (reading 'path')" during
render (it only "worked" in the minified build where with(this) falls
through to window). The defensive (countlyGlobal.path || '') form doesn't
help, since countlyGlobal.path is evaluated first.

Expose it once, centrally, on Vue.prototype via a getter (so it always
reflects the current window.countlyGlobal). This covers every dashboard
template referencing countlyGlobal across core and all plugins (including
enterprise plugins, which render in this same Vue instance) — no per-
component shims needed. JS-file uses of countlyGlobal are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Vue 2 dev/warning build render crash by making the existing window.countlyGlobal available as an instance property in Vue template expressions. It centralizes the workaround in the core Vue bootstrap so all core and plugin templates can safely reference countlyGlobal.* without per-component shims.

Changes:

  • Expose countlyGlobal on Vue.prototype using a getter that returns window.countlyGlobal.
  • Add inline documentation explaining why this is required for Vue 2’s dev-mode render proxy behavior.

@ar2rsawseen ar2rsawseen merged commit 4575ba3 into master Jun 4, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants