Repository navigation
fix(controller): render null XML values and coerce null date-select values (#4638) - #4650
Merged
Merged
Conversation
Follow-up to #4633 (#4638). renderWith()'s JSON branch is null-safe, but the XML branch still passed null struct/array/query/component values into toXML, whose required data argument rejects null and whose branches read it directly. Guard each recursion with isNull() and emit a type="null" element; a null top-level value renders as empty output in $toXml(). The date-select helpers also coerce a null bound value to "" before rendering, so no null reaches the select renderers. Regression specs cover renderWith() JSON and XML with null struct values (JSON already passed on this head; XML failed before this change) and dateSelect() with a null bound property. Add a changelog fragment. Signed-off-by: Peter Amiri <peter@alurium.com>
BoxLang indents the generated XML differently, so match type="null" with a format-agnostic FindNoCase instead of a contiguous element string. Signed-off-by: Peter Amiri <peter@alurium.com>
$toXml() is declared xml, so returning "" for a null root value throws "Cannot cast String [] to a value of type [xml]" on null-capable engines. Return a well-formed null document instead (mirroring the nested toXML element) and keep the changelog wording accurate. Cover it with a root-null spec that skips where a null cannot be passed to a required argument (Lucee null support off, RustCFML), plus a source guard that always checks the declared document shape. Strengthen the formsdate spec so a null bound property must render exactly like an empty value and produce the full 12-option month select. Signed-off-by: Peter Amiri <peter@alurium.com>
The root-null spec wrapped $toXml in try/catch and skipped on any exception, so a regression on a null-capable engine (the xml-cast error) would be skipped rather than fail. Probe null-argument support with an unrelated helper, skip only when the engine cannot pass null, then call $toXml outside any try/catch and assert toBeXML() + the null element. Keep the static source guard as the cross-engine pin. Signed-off-by: Peter Amiri <peter@alurium.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #4638 — the follow-ups r2's review of #4633 called out. #4633 made
renderWith()'s JSON branch null-safe and guarded the date/time helpers, but XML rendering of a null value still threw, and a null could still reach the date-select renderers. This PR closes both gaps.Changes (r2's patches 3 + 5)
vendor/wheels/vendor/toXml/toXML.cfc—$arrayToXML,$queryToXML,$structToXMLand$objectToXMLguard every value withisNull(...)(the only portable read form when the engine has null support off) and emit<name type="null"/>instead of recursing intotoXML()with null.$objectToXMLchecks null beforeIsCustomFunction().vendor/wheels/global/util.cfm—$toXml()returns a well-formed<?xml version="1.0" encoding="UTF-8"?><data type="null"/>document for a null top-level value instead of passing it to the requireddataargument (anxml-typed function cannot return an empty string).vendor/wheels/view/formsdate.cfc— after$dateOrTimeSelectNormalizeValue(), a null value is coerced to""before$dateOrTimeSelectRender(), so no null reaches the select renderers or child helpers.changelog.d/4638-xml-null-rendering.fixed.md(JSON-only claim from fix(controller): handle null values in renderWith() and date form helpers #4633 is now backed by the XML/formsdate fixes).Regression specs
controller/renderingSpec.cfc— "renders null struct values as json without throwing" (r2 patch 4; already passed on this head thanks to fix(controller): handle null values in renderWith() and date form helpers #4633 — kept as the JSON regression) and "renders null struct values as xml without throwing", which assertstoBeXML()and<data type="null"/>. The XML spec errors on the parent commit and passes here; with the production diff stashed the suite is 93 passed / 1 error.view/formsdateobjectSpec.cfc— "renders the select when the bound date property is null": injects ausermodel whosebirthdayisjavaCast("null", "")into the controller's variables scope under a distinct object name and asserts the select renders. The null is placed in a struct/model property, not passed to a required argument (that is not portable: required args reject null and optional args take the default on Lucee-null-off/RustCFML).Engine notes
isNull()true, so the JSON spec is vacuous on RustCFML and the formsdate test exercises the empty-value path; the XML failure is real on both engines. On Adobe/BoxLang (and Lucee with null support on) the same specs exercise the true null path; the adobe2023/boxlang CI legs cover them.nullSupportsetting), so the exact reporter configuration is inferred fromIsSimpleValue(null)=false and the unguardedtoXMLreads, as r2 documented.Verification
bash tools/test-local.sh(full core suite) → 7360 passed (7357 baseline + 3 new specs)controller/renderingSpec94 passed,view/formsdateobjectSpec9 passedFixes #4638
Final head (1483eb9): adds
tests/specs/global/toXmlRootNullSpec.cfccovering the root-null path plus the source pin, and strengthens the formsdate assertion. The live root-null test now probes null-argument support separately so it fails on null-capable engines if the guard regresses (see next commit).