diff --git a/changelog.d/3025-rootpath-anchor.fixed.md b/changelog.d/3025-rootpath-anchor.fixed.md new file mode 100644 index 0000000000..97a7d34cfd --- /dev/null +++ b/changelog.d/3025-rootpath-anchor.fixed.md @@ -0,0 +1 @@ +- The application template's `this.wheels.rootPath` now anchors to `GetCurrentTemplatePath()` (the `public/` front-controller directory) instead of `GetBaseTemplatePath()` (whatever file was originally requested). When a request bootstrapped under a subfolder — e.g. the test runner — the old base-template anchor produced an unstable path, and because `rootPath` seeds `this.name` via `Hash(rootPath)`, that silently split one app across two application scopes (the "reload=true fixes it" symptom). The value is identical for a normal front-controller request, so existing apps are unaffected (#3025, refs #2887) diff --git a/cli/lucli/templates/app/public/Application.cfc b/cli/lucli/templates/app/public/Application.cfc index 0a38c6aace..21f1dbb142 100644 --- a/cli/lucli/templates/app/public/Application.cfc +++ b/cli/lucli/templates/app/public/Application.cfc @@ -2,7 +2,16 @@ component output="false" { // Put variables we just need internally inside a wheels struct. this.wheels = {}; - this.wheels.rootPath = GetDirectoryFromPath(GetBaseTemplatePath()); + // Anchor to THIS file's directory (the public front-controller dir), not the + // base template's. GetBaseTemplatePath() returns whatever file was originally + // requested, so when a request bootstraps under a subfolder (e.g. the test + // runner) rootPath would mis-anchor — and since it seeds `this.name` via + // Hash(rootPath) below, an unstable value silently splits one app across two + // application scopes (the "reload=true fixes it" symptom in issue #3025/#2887). + // GetCurrentTemplatePath() is always this Application.cfc's path, so rootPath + // stays stable regardless of the requested base template — and is identical to + // the old value for a normal front-controller request. + this.wheels.rootPath = GetDirectoryFromPath(GetCurrentTemplatePath()); this.name = createUUID(); diff --git a/examples/starter-app/public/Application.cfc b/examples/starter-app/public/Application.cfc index 954ba4e7dc..76bc8c6639 100644 --- a/examples/starter-app/public/Application.cfc +++ b/examples/starter-app/public/Application.cfc @@ -2,7 +2,11 @@ component output="false" { // Put variables we just need internally inside a wheels struct. this.wheels = {}; - this.wheels.rootPath = GetDirectoryFromPath(GetBaseTemplatePath()); + // Anchor to this file's directory, not the requested base template's, so + // rootPath stays stable when a request bootstraps under a subfolder (e.g. + // the test runner) — Hash(rootPath) below seeds this.name, and an unstable + // value splits one app across two application scopes (issue #3025/#2887). + this.wheels.rootPath = GetDirectoryFromPath(GetCurrentTemplatePath()); this.name = createUUID(); // Give this application a unique name by taking the path to the root and hashing it. diff --git a/examples/tweet/public/Application.cfc b/examples/tweet/public/Application.cfc index 954ba4e7dc..76bc8c6639 100755 --- a/examples/tweet/public/Application.cfc +++ b/examples/tweet/public/Application.cfc @@ -2,7 +2,11 @@ component output="false" { // Put variables we just need internally inside a wheels struct. this.wheels = {}; - this.wheels.rootPath = GetDirectoryFromPath(GetBaseTemplatePath()); + // Anchor to this file's directory, not the requested base template's, so + // rootPath stays stable when a request bootstraps under a subfolder (e.g. + // the test runner) — Hash(rootPath) below seeds this.name, and an unstable + // value splits one app across two application scopes (issue #3025/#2887). + this.wheels.rootPath = GetDirectoryFromPath(GetCurrentTemplatePath()); this.name = createUUID(); // Give this application a unique name by taking the path to the root and hashing it. diff --git a/public/Application.cfc b/public/Application.cfc index b1eb617a63..af1b2c610f 100644 --- a/public/Application.cfc +++ b/public/Application.cfc @@ -2,7 +2,11 @@ component output="false" { // Put variables we just need internally inside a wheels struct. this.wheels = {}; - this.wheels.rootPath = GetDirectoryFromPath(GetBaseTemplatePath()); + // Anchor to this file's directory, not the requested base template's, so + // rootPath stays stable when a request bootstraps under a subfolder (e.g. + // the test runner) — Hash(rootPath) below seeds this.name, and an unstable + // value splits one app across two application scopes (issue #3025/#2887). + this.wheels.rootPath = GetDirectoryFromPath(GetCurrentTemplatePath()); this.name = createUUID(); // Give this application a unique name by taking the path to the root and hashing it. diff --git a/vendor/wheels/rocketunit_tests/Application.cfc b/vendor/wheels/rocketunit_tests/Application.cfc index cce8012284..2506679156 100644 --- a/vendor/wheels/rocketunit_tests/Application.cfc +++ b/vendor/wheels/rocketunit_tests/Application.cfc @@ -10,7 +10,10 @@ component { // Put variables we just need internally inside a wheels struct. this.wheels = {}; - this.wheels.rootPath = GetDirectoryFromPath(GetBaseTemplatePath()); + // Anchor to this file's directory (matches this.webrootDir below), not the + // requested base template's, so rootPath stays stable under subfolder + // bootstrap (issue #3025/#2887). + this.wheels.rootPath = GetDirectoryFromPath(GetCurrentTemplatePath()); this.webrootDir = getDirectoryFromPath( getCurrentTemplatePath() ); this.appDir = getCanonicalPath("_assets");