You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -49,6 +49,7 @@ The framework must run on Lucee 5/6/7, Adobe CF 2018/2021/2023/2025, and BoxLang
49
49
10.**Adobe CF 2023 and 2025 reject the `arguments` scope as `attributeCollection` on *any* built-in CFML tag.** Affects every `cfheader` / `cfcache` / `cfcontent` / `cfmail` / `cfdirectory` / `cffile` / `cflocation` / `cfhtmlhead` / `cfimage` / `cfdbinfo` / `cfinvoke` / `cfwddx` / `cfzip` wrapper. Covers both the string-interpolated (`attributeCollection = "#arguments#"`) and direct-struct (`attributeCollection = arguments`) forms. Adobe 2023/2025 throw — `cfheader`'s message is `"Failed to add HTML header"`; other tags surface their own — and `$header()` is catastrophic because it runs on every request. Copy to a plain struct first: `local.args = {}; for (local.key in arguments) { local.args[local.key] = arguments[local.key]; }`. Lucee 6/7, BoxLang, and Adobe 2018/2021 accept both forms; Adobe 2023/2025 require the plain struct. The 13 sites in `vendor/wheels/Global.cfc` were patched uniformly in [#2750](https://github.com/wheels-dev/wheels/pull/2750).
50
50
11.**`local.X = ...` inside `catch` doesn't persist on BoxLang.** Catch body runs under a nested `local` that gets discarded on exit, so `expect(local.X)` after the catch reads the un-touched outer value. Use a struct field: `var state = {flag = false}; ... state.flag = true;`. Bare `var bareName` + unscoped `bareName = true` also works but the struct form mirrors `TenantResolverSpec` and is the prior-art pattern.
51
51
12.**`for (local.i = ...)` inside `finally` miscompiles on Lucee 7.** Lucee 7.0.1+100 throws `variable [local] doesn't exist` at runtime when a `for` loop declares or iterates `local`-/`var`-scoped variables inside a `finally` block (one probe shape even produced a JVM `Expecting a stackmap frame` verifier error). Bare assignments and function calls in `finally` are fine; loops are not. Hoist the loop into a `public``$`-prefixed helper and call it from `finally` — reference: `$restoreEmailViewVariables()` in `vendor/wheels/controller/miscellaneous.cfc` ([#2922](https://github.com/wheels-dev/wheels/pull/2922)).
52
+
13.**Bare tag-in-script statements without parentheses (e.g. `cfabort;`) are Lucee-only.** Adobe CF compiles the bare token as a reference to an undefined VARIABLE and throws `Variable CFABORT is undefined` at runtime (every Adobe engine, not just one release). Use the script keyword (`abort;`) or the parenthesized call form (`cfheader(...)`-style) instead. The `enablePublicComponent=false` 404 branch in `vendor/wheels/Dispatch.cfc` shipped a bare `cfabort;`, which turned `GET /` on every stock Adobe install in `testing`/`production` into an HTTP 500 ([#3029](https://github.com/wheels-dev/wheels/issues/3029)). Structural guard: `vendor/wheels/tests/specs/security/BareCfabortGuardSpec.cfc` fails the suite if any bare script-context `cfabort` statement reappears under `vendor/wheels/**/*.cfc` (tag-context `<cfabort>` in `.cfm`/tag-based CFCs stays legal).
52
53
53
54
Verify Adobe CF fixes locally before pushing — don't iterate via CI:
-`wheels test` (and `wheels browser test`) now honour the `subpath` setting for subfolder-mounted apps via a new `--base-path` flag, auto-deriving the prefix from `WHEELS_SUBPATH` or `set(subpath=...)` when omitted, so the test runner is reachable under a URL prefix instead of always assuming a root mount (#3026)
- Dispatch: the `enablePublicComponent=false` anti-fingerprinting 404 branch ended in a bare `cfabort;`, which is Lucee-only tag-in-script syntax — every Adobe engine threw `Variable CFABORT is undefined` at runtime, turning `GET /` (and every `/wheels/*` request) on a stock app in `testing`/`production` into an HTTP 500 instead of a clean `404 Not Found`. Replaced with the script keyword `abort;`, and a new structural guard spec (`BareCfabortGuardSpec`) fails the suite if a bare script-context `cfabort` statement ever reappears under `vendor/wheels` (#3029)
- URL environment switching (`?reload=<environment>&password=...`) now works through the app template's `applicationStop()` reload flow: the restart redirect preserves `reload` + `password` for environment switches (plain `?reload=true` still strips everything), the configured `reloadPassword` is handed across the restart via a single-use server-scope entry so the framework's switch code can verify it on the cold start, and the reload gate skips the restart once the requested environment is active so the redirect chain always terminates. `allowEnvironmentSwitchViaUrl` is enforced pre-restart: when switching is disallowed — `set(allowEnvironmentSwitchViaUrl=false)` or the framework's production/testing/maintenance auto-disable — the parameters are stripped and the request degrades to a plain restart, preserving the existing hardening (the framework cannot enforce the flag itself after `applicationStop()` destroys its carryover state). Applied to all four `public/Application.cfc` copies (CLI app template, repo demo app, starter-app and tweet examples). Trade-off: `?reload=<current-environment>` is now a no-op — use `?reload=true` for a same-environment restart (#3030)
- Explicit `set(allowEnvironmentSwitchViaUrl=true)` in `config/settings.cfm` is now honored in production-like environments (production, testing, maintenance). It used to be indistinguishable from the framework default and was silently discarded, making the documented override impossible (#3031)
.option(name ="db", default ="sqlite", description ="Database the suite runs against")
277
+
.option(name ="base-path", default ="", description ="URL prefix the app is mounted under (e.g. /myapp). Auto-derived from WHEELS_SUBPATH or set(subpath=...) when omitted.")
277
278
.flag(name ="verbose", default =false, description ="Print per-spec detail instead of the summary rollup")
0 commit comments