Skip to main content

Overview

PathResolver provides secure dot-notation path resolution with caching and prototype pollution protection.
Note: PathResolver is used internally by RuleEngine. You typically use engine.resolvePath() instead of accessing PathResolver directly.

resolvePath()

Resolve a dot-notation path to a value.
const value = engine.resolvePath(context, path, defaultValue);

Parameters

context
object
required
Object to resolve path in
path
string
required
Dot-notation path (e.g., ‘user.profile.name’)
defaultValue
any
Value to return if path doesn’t exist

Returns

Resolved value or defaultValue if path doesn’t exist.

Examples

  • Basic
  • Missing Paths
  • Arrays
  • Nested Objects
const data = {
  user: {
    name: 'John',
    profile: {
      age: 25,
      email: 'john@example.com'
    }
  }
};

engine.resolvePath(data, 'user.name');
// 'John'

engine.resolvePath(data, 'user.profile.age');
// 25

engine.resolvePath(data, 'user.profile.email');
// 'john@example.com'

Security Features

Prototype Pollution Protection

PathResolver blocks dangerous paths by default:
const data = {};

// Blocked: prototype access
engine.resolvePath(data, '__proto__');
// undefined (blocked)

engine.resolvePath(data, 'constructor');
// undefined (blocked)

engine.resolvePath(data, '__proto__.polluted');
// undefined (blocked)
Never set allowPrototypeAccess: true in production. It opens security vulnerabilities.

Function Blocking

Functions are blocked by default:
const data = {
  getName: function() { return 'John'; }
};

engine.resolvePath(data, 'getName');
// undefined (blocked - it's a function)

Caching

PathResolver caches resolutions for performance:
// First call - cache miss
engine.resolvePath(data, 'user.profile.name'); // Resolves and caches

// Second call - cache hit (faster)
engine.resolvePath(data, 'user.profile.name'); // Retrieved from cache

Clear Cache

engine.clearCache();
// Clears both expression and path caches

Advanced Usage

Direct PathResolver Access

// Access internal PathResolver (rare)
const pathResolver = engine._internal.pathResolver;

// Use NOT_FOUND symbol
const value = pathResolver.resolve(data, path, pathResolver.NOT_FOUND);

if (value === pathResolver.NOT_FOUND) {
  console.log('Path does not exist');
}

Literal Values

// resolveValueOrLiteral handles both paths and literals
const pathResolver = engine._internal.pathResolver;

pathResolver.resolveValueOrLiteral(data, 'user.name');
// Resolves path → 'John'

pathResolver.resolveValueOrLiteral(data, 'literal-string');
// Returns literal → 'literal-string'

pathResolver.resolveValueOrLiteral(data, 123);
// Returns literal → 123

Configuration

Configure via engine config:
const engine = createRuleEngine({
  allowPrototypeAccess: false,  // Block prototype (default: false)
  maxCacheSize: 1000,           // Path cache size
  enableCache: true             // Enable caching (default: true)
});

Common Patterns

// Instead of optional chaining
const email = data?.user?.profile?.email;

// Use resolvePath with default
const email = engine.resolvePath(data, 'user.profile.email', null);
const fields = ['user.name', 'user.email', 'user.age'];

const values = fields.map(field =>
  engine.resolvePath(data, field)
);
function validateRequired(data, paths) {
  return paths.every(path => {
    const value = engine.resolvePath(data, path);
    return value !== null && value !== undefined;
  });
}

validateRequired(data, ['user.name', 'user.email']);

Error Handling

PathResolver doesn’t throw errors - it returns undefined or defaultValue:
// All return undefined (not errors)
engine.resolvePath(null, 'path');
engine.resolvePath(undefined, 'path');
engine.resolvePath({}, 'nonexistent.path');
engine.resolvePath({}, '__proto__'); // Blocked path