Core Concepts

Identifier owner resolver

Determines which object in the expression context owns a given identifier. RS-X iterates a pluggable resolver list and returns the first non-null owner.

What it means

When an expression like a + b is evaluated, each identifier (a, b) must be resolved to an owner — the object that contains it. IIdentifierOwnerResolver defines this contract: resolve(index, context) returns the owning object or null to pass to the next resolver in the list.

DefaultIdentifierOwnerResolver is the default implementation. It holds an ordered resolver list via DI (IIdentifierOwnerResolverList) and iterates until one returns a non-null owner.

The default list, in priority order:

Practical value

RS-X is environment-agnostic. Adding a custom resolver lets you introduce new owner-lookup rules — for example, walking a component tree in a web-component framework — without changing core expression logic. Replace or reorder the default list with overrideMultiInjectServices.

Resolution order and the first-non-null rule

DefaultIdentifierOwnerResolver iterates IIdentifierOwnerResolverList in registration order. The first resolver that returns a non-null value wins. This means you can prepend a high-priority resolver to intercept identifiers before the standard property lookup.

If no resolver claims the identifier, resolve() returns null. RS-X then falls back to the next context in the expression binding chain.

Adding a custom resolver

Implement IIdentifierOwnerResolver and register it with registerMultiInjectServices(options, RsXExpressionParserInjectionTokens.IIdentifierOwnerResolverList, [...]). The new resolver is appended after the built-in defaults.

To replace the full list or change priority order, call overrideMultiInjectServices with the complete desired list, including any built-in resolvers you want to keep.

Example

import {
  ContainerModule,
  Injectable,
  InjectionContainer,
  registerMultiInjectServices,
} from '@rs-x/core';
import {
  type IIdentifierOwnerResolver,
  rsx,
  RsXExpressionParserInjectionTokens,
  RsXExpressionParserModule,
} from '@rs-x/expression-parser';

// A shared constants store — values are accessible from any expression
// without having to include them in every model object.
const constants: Record<string, unknown> = {
  TAX_RATE: 0.21,
  SHIPPING_FLAT: 5,
};

@Injectable()
class ConstantsOwnerResolver implements IIdentifierOwnerResolver {

Related docs