December 2025 (version 2.25.12.18)
reviewed: 18 December 2025
🚀 New Features
Response Start Detection
A new response function has been added:
response.hasStarted()
If true, the response has begun and headers have already been sent to the client.
<@url> Variants for Document Viewing and Downloading
We’ve added two new <@url> qualifier variants that simplify generating URLs for viewing and downloading documents.
<@url/document/view
document:[document]
>
<@url/document/download
document:[document]
>
These qualifiers work anywhere a standard <@url> is accepted, and they can be dropped straight into qualifiers such as <@page/button>.
With these additions, developers no longer need to hand craft the URL generation logic, just use the appropriate qualifier and the correct link is produced automatically.
🔧 Updates
Property Bag Enhancements
Property bag resolution is now composable
Resolving a property bag now returns itself:
<
translations: pb.resolve([translations])
// ...
>
pb.set() now returns the value that was set
This makes it easier to chain with other functions:
if pb.set([pb], 'isValid', script.call('./validate'))
// ...
end-if
Nested property deletion support
You can now delete nested items using paths:
pb.delete([pb], 'assets/1/value')
Previously, deleting nested paths would not error but would also not delete.
Improved raise Statement Support
The raise statement now accepts a qualifier directly as the message, which is automatically invoked:
raise exceptionType.fatal, <@text EN: 'Something has gone wrong' NL: 'Er is iets misgegaan'>
Manual qualifier.invoke() usage will still work, but is no longer necessary.
Icon Qualifier Improvements
- Added excluded support
- Added tooltip support
Simplified Inline Tooltip Support
Previously, tooltips always required a full qualifier:
<@page/icon
name: 'box'
tooltip: <@page/tooltip
label: 'My tooltip'
>
>
Now, simple tooltips can also be expressed directly:
<@page/icon
tooltip: 'My tooltip'
>
- Any qualifier can be used as a simplified tooltip (
<@page/text>for example) and will be automatically invoked and escaped. - If the qualifier provided is as a
<@page/...>qualifier, the tooltip is automatically marked as HTML-safe. - Full
<@page/tooltip>remains supported for more complex requirements.
🐞 Fixes
Report Builder
- For SQL reports the dynamic Business Object is now regenerated when changing the reports datasource.
Isolated Context Groups
Whitespace in the context group is now ignored correctly:
set('name', 'Seth')
set('age', 10)
isolate 'name, age'
page.render([name]) // "Seth"
page.render([age]) // Previously "", now "10"
end-isolate 'name'
Inline View Descriptor Handling
Fixed an issue where setting inLineView to null() was incorrectly treated as if an inline view existed.
Active Expression Stability
Errors from active expressions in the Report Builder, Application Maintenance, and Ad-hoc Queries are now captured and logged, but not thrown.
The pages will now display, minus any erroneous entries.
Form Transaction Handling
Exceptions captured by _onError() no longer cause a transaction rollback when submitting an <@page/data/form>.
Property Bag Merge Fixes
Anonymous (unnamed) items are now always merged correctly and assigned a new internal GUID each time. This ensures correct behavior when merging qualifiers from within the script cache.
Where Clause Special Case Sensitivity
The special tokens used in WHERE clauses (e.g., #null, #true, etc.) are now treated case‑insensitively, so #NULL, #True, or any other capitalization will be recognized correctly.
🔒 Security
Safer Redirect Behavior
Buffered response bodies are no longer returned to the client during response.redirect().
If needed, a response body can still be forced via response.flush(), but this is now an intentional operation.
Thread-Safe Procedure Default Values
Default parameter values in script procedures are now thread-safe.
Example of the previous issue (mutating shared defaults):
function example(pb: <>)
pb.set(guid([pb]), guid())
return [pb]
end-if
// After three calls without passing a pb parameter,
// the returned property bag would accumulate values like this:
// <
// 1f8b2a3c-7d4e-41f9-a6b5-9c3e2d7f1a84: "e5c9d2b1-3a6f-44b2-9d78-2f1e6c5b7d90"
// a3d4e6f9-8b2c-4a71-93e5-5d7c1b2a8f33: "7e9f2c4b-1a5d-48e3-b6a9-0c3d5f7e2b11"
// c2b1d8e4-6f3a-49c2-8d7e-1a9b3c5d6f22: "9a7c5e3b-2d4f-47a1-9c6b-3e8f1d2a5c77"
// >
Default parameter values no longer persist mutated state across calls.
XSS Vulnerability Fix
Fixed an XSS vulnerability in:
- Select input placeholders
- Select input option values
This impacted both option list selects and foreign key selects.
Select2 Service Replay Fix
- Previously generated descriptors now return 403.
- Descriptors are now tied to the specific user that generated them.
- Sessionless systems are unaffected (descriptors are inherently public).
Dedicated Email Out Profile Page
A new optional page has been added to prevent exposing passwords on systems with strict credential-handling requirements.
To enable:
- Update the application maintenance entry for email out profiles.
- Change entity from
email/outProfile→null - Set the URL to:
application/maintenance/email/outProfile:main