Skip to content

feat: Support objects in frontend expressions - #18982

Merged
TomasEng merged 44 commits into
mainfrom
support-objects-in-expressions
Jun 18, 2026
Merged

feat: Support objects in frontend expressions#18982
TomasEng merged 44 commits into
mainfrom
support-objects-in-expressions

Conversation

@TomasEng

@TomasEng TomasEng commented May 27, 2026

Copy link
Copy Markdown
Contributor

Important

This pull request is stacked upon #18974, which should be merged first.

Description

This pull request adds support for objects in frontend expressions, along with an object function for creating an object. Here is an overview of the changes:

  • New object type in ExprVal
  • New object function in expression-functions, using a new class named ObjectFunctionEvaluator

Here is the corresponding change in App Backend: Altinn/app-lib-dotnet#1777

Verification

  • Related issue: Support objects in expressions app-frontend-react#4190
  • Your code builds clean without any errors or warnings
  • Manual testing not possible since there is no use case for this until we add functions that accept objects as parameters; the automated unit tests should be sufficient
  • Relevant automated test added (if you find this hard, leave it and we'll help out)

Summary by CodeRabbit

  • New Features
    • Added object literal support to the expression language, including object/strict-object validation.
    • Introduced an object() function to construct objects from key/value pairs (with validation for even argument counts, string keys, and unique keys).
    • Extended expression evaluation and casting to handle object values, including safe pass-through for any.
  • Tests
    • Added and expanded expression fixtures and coverage for object creation, lookups, and list/object combinations.
  • Bug Fixes
    • Removed an outdated test fixture for “object lookup returns null” to reflect current behavior.

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 39efc27c-26c1-475d-9b02-890e090bf24f

📥 Commits

Reviewing files that changed from the base of the PR and between b11ea0a and 995a992.

📒 Files selected for processing (1)
  • src/App/frontend/src/features/expressions/validation.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/App/frontend/src/features/expressions/validation.ts

📝 Walkthrough

Walkthrough

Adds ExprVal.Object as a new first-class expression value type across the expression mini-language. This includes type definitions, ValidObject validation helpers, an ObjectFunctionEvaluator class, registration of the object(...) function, JSON Schema extensions, codegen mappings, new array utility functions, and shared test fixtures.

Changes

Object Expression Type

Layer / File(s) Summary
Core types and validation
src/App/frontend/src/features/expressions/types.ts, src/App/frontend/src/features/expressions/validation.ts
ExprVal.Object enum member added; ExprValToActual and ValidValue extended with ValidObject; isValidObject exported and isValidValue updated to accept objects recursively.
Array utility helpers
src/App/frontend/src/utils/arrayUtils.ts, src/App/frontend/src/utils/arrayUtils.test.ts
New module exports consistsOfStringsOnly, areStringsUnique, and zipArrays, each with full Jest test coverage.
ObjectFunctionEvaluator
src/App/frontend/src/features/expressions/ObjectFunctionEvaluator.ts
New class partitions alternating key/value argument lists, validates keys as unique strings, and returns an Object.fromEntries result; throws ExprRuntimeError on invalid input.
Expression function registry and ExprTypes wiring
src/App/frontend/src/features/expressions/expression-functions.ts, src/App/frontend/src/features/expressions/index.ts
object function registered in ExprFunctionDefinitions, ExprFunctionImplementations, and ExprFunctionValidationExtensions; ExprTypes extended with ExprVal.Object handler; ExprVal.Any acceptance expanded to include ExprVal.Object.
JSON Schema and codegen mappings
src/App/frontend/schemas/json/layout/expression.schema.v1.json, src/App/frontend/src/codegen/dataTypes/GenerateExpressionOr.ts
definitions.any.anyOf extended with strict-object; new object, strict-object, and func-object schema definitions added; GenerateExpressionOr toTsMap and toSchemaMap updated for ExprVal.Object.
Shared test fixtures
src/App/frontend/src/features/expressions/shared-tests/functions/object/object.json, src/App/frontend/src/features/expressions/shared-tests/functions/dataModel/lookup-object.json, src/App/frontend/src/features/expressions/shared-tests/functions/dataModel/lookup-list.json, src/App/frontend/src/features/expressions/shared-tests/functions/list/list.json
New object.json and lookup-object.json fixtures added; lookup-list.json updated with objectList and differentTypesList coverage; list.json gains a "Supports objects" case; superseded object-is-null.json removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Altinn/altinn-studio#18974: Follows the same pattern of adding a new ExprVal variant (list) — updates definitions.any.anyOf in the expression JSON schema, extends the function registry, and expands ExprVal.Any acceptance in ExprTypes.

Suggested labels

solution/studio/designer, quality/testing

Suggested reviewers

  • olemartinorg
  • olavsorl

Poem

A rabbit hopped in, paws full of keys,
Paired with their values, tucked in with ease.
object("city", "Oslo") — done in a flash,
Even args only, or errors we'll clash!
🐇✨ Now objects are valid, no nulls left to mourn.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Support objects in frontend expressions' directly and clearly describes the main change—adding object support to the expression system.
Description check ✅ Passed The description covers the key aspects: what was added (object type and function), references to related PRs and issues, verification checklist completion, and rationale for testing approach.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch support-objects-in-expressions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the skip-releasenotes Issues that do not make sense to list in our release notes label May 27, 2026
@TomasEng
TomasEng force-pushed the support-objects-in-expressions branch from 0cc8994 to fe6d2e2 Compare May 28, 2026 13:21
@TomasEng TomasEng moved this to 👷 In progress in Team Altinn Studio May 29, 2026
@TomasEng TomasEng added frontend squad/data Issues that belongs to the named squad. labels May 29, 2026
@TomasEng

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@TomasEng TomasEng moved this from 👷 In progress to 🔎 In review in Team Altinn Studio May 29, 2026
@TomasEng
TomasEng marked this pull request as ready for review May 29, 2026 08:23
Comment thread src/App/frontend/schemas/json/layout/expression.schema.v1.json Outdated
Comment thread src/App/frontend/src/features/expressions/ObjectFunctionEvaluator.ts Outdated
@TomasEng
TomasEng requested a review from olemartinorg June 16, 2026 14:03
Base automatically changed from support-lists-in-expressions to main June 17, 2026 05:23

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/App/frontend/src/codegen/dataTypes/GenerateExpressionOr.ts (1)

7-24: ⚠️ Potential issue | 🟠 Major

Extend TypeMap to support ExprVal.Object.

The lookup entries in toTsMap and toSchemaMap have been correctly updated for ExprVal.Object, but TypeMap (lines 27–33) still only handles Boolean, Number, and String. This means GenerateExpressionOr<ExprVal.Object> incorrectly resolves to never, breaking the type contract even though no current code instantiates this variant. Add the missing conditional branch to TypeMap before this generator is used with Object types.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/App/frontend/src/codegen/dataTypes/GenerateExpressionOr.ts` around lines
7 - 24, The TypeMap type definition does not include a conditional branch for
ExprVal.Object, which causes GenerateExpressionOr to incorrectly resolve to
never for Object types even though toTsMap and toSchemaMap have been correctly
updated with Object entries. Add a conditional branch to TypeMap that mirrors
the pattern used for ExprVal.Boolean, ExprVal.Number, and ExprVal.String to
properly handle the ExprVal.Object case and return the correct type mapping.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/App/frontend/src/features/expressions/validation.ts`:
- Around line 349-351: The isValidObject function in the validation.ts file uses
typeof value === 'object' which returns true for arrays and class instances like
Date, causing arrays and non-plain objects to be incorrectly accepted as valid
objects. Fix this by adding a check to exclude arrays using Array.isArray(value)
and to ensure the value is a plain object rather than a class instance. Add
!Array.isArray(value) to the condition, and additionally verify that
Object.getPrototypeOf(value) === Object.prototype to exclude class instances and
ensure only plain objects are accepted as valid objects.

---

Outside diff comments:
In `@src/App/frontend/src/codegen/dataTypes/GenerateExpressionOr.ts`:
- Around line 7-24: The TypeMap type definition does not include a conditional
branch for ExprVal.Object, which causes GenerateExpressionOr to incorrectly
resolve to never for Object types even though toTsMap and toSchemaMap have been
correctly updated with Object entries. Add a conditional branch to TypeMap that
mirrors the pattern used for ExprVal.Boolean, ExprVal.Number, and ExprVal.String
to properly handle the ExprVal.Object case and return the correct type mapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2c2eb29a-5c9f-4e15-b4a3-9e7a35948f15

📥 Commits

Reviewing files that changed from the base of the PR and between f648c3e and b11ea0a.

📒 Files selected for processing (14)
  • src/App/frontend/schemas/json/layout/expression.schema.v1.json
  • src/App/frontend/src/codegen/dataTypes/GenerateExpressionOr.ts
  • src/App/frontend/src/features/expressions/ObjectFunctionEvaluator.ts
  • src/App/frontend/src/features/expressions/expression-functions.ts
  • src/App/frontend/src/features/expressions/index.ts
  • src/App/frontend/src/features/expressions/shared-tests/functions/dataModel/lookup-list.json
  • src/App/frontend/src/features/expressions/shared-tests/functions/dataModel/lookup-object.json
  • src/App/frontend/src/features/expressions/shared-tests/functions/dataModel/object-is-null.json
  • src/App/frontend/src/features/expressions/shared-tests/functions/list/list.json
  • src/App/frontend/src/features/expressions/shared-tests/functions/object/object.json
  • src/App/frontend/src/features/expressions/types.ts
  • src/App/frontend/src/features/expressions/validation.ts
  • src/App/frontend/src/utils/arrayUtils.test.ts
  • src/App/frontend/src/utils/arrayUtils.ts
💤 Files with no reviewable changes (1)
  • src/App/frontend/src/features/expressions/shared-tests/functions/dataModel/object-is-null.json

Comment thread src/App/frontend/src/features/expressions/validation.ts
@TomasEng
TomasEng merged commit ae15d2d into main Jun 18, 2026
20 of 21 checks passed
@github-project-automation github-project-automation Bot moved this from 🔎 In review to ✅ Done in Team Altinn Studio Jun 18, 2026
@TomasEng
TomasEng deleted the support-objects-in-expressions branch June 18, 2026 12:57
@TomasEng
TomasEng restored the support-objects-in-expressions branch June 18, 2026 12:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend skip-releasenotes Issues that do not make sense to list in our release notes squad/data Issues that belongs to the named squad.

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants