diff --git a/.ai/wheels/cross-engine-compatibility.md b/.ai/wheels/cross-engine-compatibility.md index ee867aabc8..c613646c8b 100644 --- a/.ai/wheels/cross-engine-compatibility.md +++ b/.ai/wheels/cross-engine-compatibility.md @@ -233,6 +233,27 @@ private string function myHelper() { ... } public string function $myHelper() { ... } ``` +### `attributeCollection` with the `arguments` Scope (Adobe CF 2023) + +Adobe CF 2023 rejects the raw `arguments` scope when passed as `attributeCollection` to *any* built-in CFML tag, throwing engine-specific errors (`cfheader` reports `"Failed to add HTML header"`) and aborting the request. Lucee 6/7, BoxLang, and Adobe CF 2018/2021 all accept the `arguments` scope without complaint. Both the string-interpolated form (`attributeCollection = "#arguments#"`) and the CFScript direct-struct form (`attributeCollection = arguments`) are affected. + +```cfm +// WRONG — crashes Adobe CF 2023 +cfheader(attributeCollection = "#arguments#"); +cfimage(attributeCollection = arguments); + +// RIGHT — copy to a plain struct first +local.args = {}; +for (local.key in arguments) { + local.args[local.key] = arguments[local.key]; +} +cfheader(attributeCollection = "#local.args#"); +``` + +**Why**: Adobe CF 2023 imposes a stricter type check on `attributeCollection` and requires a plain CFML struct, not the special `arguments` scope object. The struct-copy pattern is safe and idiomatic across all engines. `$header()` is the dispatch-path blocker (runs on every request) — the others surface as soon as the corresponding helper is called. + +**Reference fix**: [#2750](https://github.com/wheels-dev/wheels/pull/2750) (closes #2741) — patches all 13 affected wrappers in `vendor/wheels/Global.cfc` uniformly: `$header`, `$cache`, `$content`, `$mail`, `$directory`, `$file`, `$location`, `$htmlhead`, `$image`, `$dbinfo`, `$invoke`, `$wddx`, `$zip`. `$dbinfo()` rebuilds the local copy before each of its four `cfdbinfo` calls because the catch path mutates `arguments` between calls — a useful pattern when a helper writes through `arguments` between tag invocations. + ## Database-Specific Gotchas ### H2 Database (Test Default) diff --git a/CLAUDE.md b/CLAUDE.md index 386f3b412e..edab19e191 100755 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,6 +46,7 @@ The framework must run on Lucee 5/6/7, Adobe CF 2018/2021/2023/2025, and BoxLang 7. **`private` mixin functions are not integrated.** `$integrateComponents()` only copies `public` methods into model/controller objects. ALL helpers in `vendor/wheels/model/*.cfc`, view helpers, etc. MUST use `public` access with `$` prefix for internal scope. BoxLang passes; Lucee/Adobe fail. 8. **`Left(str, 0)` crashes Lucee 7.** Guard: `len > 0 ? Left(str, len) : ""`. 9. **`toBeInstanceOf("component")` fails on BoxLang** — returns the FQN, not the literal `"component"`. Use `toBeWheelsModel()` for finder results. +10. **Adobe CF 2023 rejects 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 throws — `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 requires the plain struct. The 13 sites in `vendor/wheels/Global.cfc` were patched uniformly in [#2750](https://github.com/wheels-dev/wheels/pull/2750). Verify Adobe CF fixes locally before pushing — don't iterate via CI: ```bash