Skip to content

Commit a466c5d

Browse files
committed
docs: extend attributeCollection invariant to Adobe CF 2023 and 2025
Reviewer A round 1 on #2755 caught a real correctness gap: develop's `Global.cfc::$header()` comment explicitly says "Adobe CF 2023+ rejects the raw arguments scope" — the `+` is load-bearing — and #2750 patched all 13 wrappers precisely because the restriction extends past 2023. The docs as previously written named only "Adobe CF 2023", giving a developer reading invariant #10 no signal to guard their code on Adobe CF 2025. Updates: - CLAUDE.md invariant #10: "Adobe CF 2023" → "Adobe CF 2023 and 2025" throughout (opener, throw clause, "require the plain struct" clause). - .ai/wheels/cross-engine-compatibility.md: section heading is "(Adobe CF 2023/2025)"; intro and Why paragraph name both engines; WRONG block comment says "crashes Adobe CF 2023 and 2025". - RIGHT example in the .ai/ doc now mirrors the WRONG block by showing both invocation forms working once `local.args` is a plain struct (cfheader interpolated form + cfimage direct form), with a brief comment explaining why both are safe at that point — addresses Reviewer A's non-blocking nit that the original RIGHT example showed only the string-interpolated form while $image() uses the direct form. Engine matrix is unchanged otherwise: Lucee 6/7 + BoxLang + Adobe 2018/2021 still accept; Adobe 2023/2025 reject. Signed-off-by: Peter Amiri <peter@alurium.com>
1 parent 3691aa1 commit a466c5d

2 files changed

Lines changed: 9 additions & 6 deletions

File tree

.ai/wheels/cross-engine-compatibility.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,24 +233,27 @@ private string function myHelper() { ... }
233233
public string function $myHelper() { ... }
234234
```
235235

236-
### `attributeCollection` with the `arguments` Scope (Adobe CF 2023)
236+
### `attributeCollection` with the `arguments` Scope (Adobe CF 2023/2025)
237237

238-
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.
238+
Adobe CF 2023 and 2025 reject 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.
239239

240240
```cfm
241-
// WRONG — crashes Adobe CF 2023
241+
// WRONG — crashes Adobe CF 2023 and 2025
242242
cfheader(attributeCollection = "#arguments#");
243243
cfimage(attributeCollection = arguments);
244244
245-
// RIGHT — copy to a plain struct first
245+
// RIGHT — copy to a plain struct first; either invocation form works once
246+
// `local.args` is a plain struct (the engine's stricter check only objects
247+
// to the special `arguments` scope object, not to the form of the call).
246248
local.args = {};
247249
for (local.key in arguments) {
248250
local.args[local.key] = arguments[local.key];
249251
}
250252
cfheader(attributeCollection = "#local.args#");
253+
cfimage(attributeCollection = local.args);
251254
```
252255

253-
**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.
256+
**Why**: Adobe CF 2023 and 2025 impose a stricter type check on `attributeCollection` and require 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.
254257

255258
**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.
256259

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ The framework must run on Lucee 5/6/7, Adobe CF 2018/2021/2023/2025, and BoxLang
4646
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.
4747
8. **`Left(str, 0)` crashes Lucee 7.** Guard: `len > 0 ? Left(str, len) : ""`.
4848
9. **`toBeInstanceOf("component")` fails on BoxLang** — returns the FQN, not the literal `"component"`. Use `toBeWheelsModel()` for finder results.
49-
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).
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).
5050

5151
Verify Adobe CF fixes locally before pushing — don't iterate via CI:
5252
```bash

0 commit comments

Comments
 (0)