Architecture

Deep dive into fast-brake's high-performance pattern matching system and plugin architecture

How fast-brake Works

fast-brake uses pattern matching and a plugin architecture for fast feature detection.

graph TD
    A[JavaScript Code] --> B[Pattern Matching Engine]
    B --> C[Regex-based Feature Detection]
    C --> D[Feature Results]
    D --> E{Include Location?}
    E -->|Yes| F[Calculate Location Data]
    E -->|No| G[Return Results]
    F --> G[Return Results]

This approach delivers up to 85x faster performance with targeted plugins compared to traditional AST parsers.

Module Types

Fast Brake has three types of optional, composable modules:

ModulePurposeLocationExamples
PreprocessorsTransform code before detectionsrc/plugins/ (core)jscomments - strips comments/strings
PluginsDefine detection patterns/schemassrc/plugins/ (bundled)esversion - ES feature patterns
ExtensionsEnrich detection resultsextensions/ (separate packages)fast-brake-acorn - AST validation

Preprocessors

Preprocessors prepare code for accurate detection. The jscomments preprocessor is core infrastructure - parsing JavaScript without comment/string awareness produces unreliable results.

Preprocessors with external dependencies (TypeScript, JSX, Flow) are separate packages:

  • fast-brake-typescript-preprocessor
  • fast-brake-jsx-preprocessor
  • fast-brake-flow-preprocessor

Plugins

Plugins answer: “What are we looking for?”

They provide pattern schemas for detection. Bundled plugins (esversion, telemetry) have no external dependencies and ship with fast-brake.

Extensions

Extensions answer: “What else can we learn about the match?”

They enrich results post-detection (line numbers, AST validation, code frames). Extensions with external dependencies live in extensions/ as separate workspace packages that users install as needed.

Core Architecture Components

1. Detector Engine (src/detector.ts)

The Detector is the main engine that performs pattern-based feature detection.

class Detector {
  // High-performance pattern scanning
  scan(code: string, options?: DetectionOptions): DetectedFeature[]
  
  // Main detection method
  detect(code: string, options: DetectionOptions): DetectedFeature[]
  
  // Check compatibility
  check(code: string, options: DetectionOptions): boolean
  
  // Get minimum ES version
  getMinimumVersion(code: string): string
}

Key Responsibilities:

  • Manages compiled regex patterns for optimal performance
  • Performs single-pass pattern matching
  • Provides location data when requested
  • Singleton instance for performance optimization

2. Plugin System (src/plugins/)

The Plugin System allows targeted detection for specific use cases.

Plugin Interface Schema
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Available Plugins:

  • ES Version Plugins: es5, es2015, es2016, etc.
  • All Plugin: Detects all ES features
  • Browser Plugin: Browser compatibility checking
  • Telemetry Plugin: Analytics detection
  • Detect Plugin: Auto-detect minimum version

3. Pattern Engine (src/constants.ts)

The Pattern Engine contains optimized regex patterns and feature mappings.

// Quick detection patterns
export const QUICK_PATTERNS: Record<string, RegExp> = {
  arrow_functions: /=>/,
  template_literals: /`/,
  optional_chaining: /\?\./,
  // ... 40+ patterns
};

// Feature version mappings
export const FEATURE_VERSIONS: Record<string, string> = {
  arrow_functions: 'es2015',
  optional_chaining: 'es2020',
  private_fields: 'es2022',
  // ... complete mappings
};

Optimization Strategies:

  • Pre-compiled patterns: Regex patterns compiled at startup
  • Hierarchical organization: Patterns grouped by ES version
  • Performance tuning: Optimized for common cases first

Pattern Matching Deep Dive

High-Performance Detection

Objective: Fast feature detection using optimized regex patterns.

// Example: Detecting arrow functions
const arrowPattern = /=>/;
const matches = code.match(arrowPattern);
if (matches) {
  features.push({
    name: 'arrow_functions',
    version: 'es2015',
    line: getLineNumber(matches.index),
    column: matches.index
  });
}

Characteristics:

  • Ultra-fast: ~0.001ms with targeted plugins
  • High accuracy: Carefully crafted patterns
  • Single-pass: Processes code once

Use Cases:

  • Development builds with hot reloading
  • Build tools where speed is critical
  • CI/CD pipelines for compatibility checking

Location Data Support

Provides optional AST-like location information.

// Example: Getting location data
const features = detect(code, { includeLoc: true });
// Returns:
// {
//   name: 'arrow_functions',
//   version: 'es2015',
//   loc: {
//     start: { line: 1, column: 15 },
//     end: { line: 1, column: 17 },
//     offset: 14,
//     length: 2
//   }
// }

Characteristics:

  • Precise locations: Line, column, offset, and length
  • Optional feature: No overhead unless requested
  • AST compatibility: Similar to parser output
  • Minimal overhead: Calculated only when needed

Performance Optimizations

1. Singleton Pattern

let detectorInstance: Detector | null = null;

export function getDetector(): Detector {
  if (!detectorInstance) {
    detectorInstance = new Detector();
  }
  return detectorInstance;
}

Benefits:

  • Reuses compiled regex patterns
  • Reduces memory allocation
  • Faster subsequent calls

2. Pattern Compilation

class Detector {
  private compiledPatterns: Map<string, RegExp>;
  
  constructor() {
    // Compile all patterns once at startup
    this.compiledPatterns = new Map();
    for (const [name, pattern] of Object.entries(QUICK_PATTERNS)) {
      this.compiledPatterns.set(name, pattern);
    }
  }
}

Benefits:

  • Patterns compiled once, used many times
  • Eliminates regex compilation overhead
  • Consistent performance across calls

3. Early Termination

// Stop on first incompatible feature
if (options.throwOnFirst && featureIndex > targetIndex) {
  throw new Error(`Incompatible feature: ${feature.name}`);
}

Benefits:

  • Faster failure detection
  • Reduced processing for incompatible code
  • Better CI/CD performance

4. Memory Efficiency

// Minimal allocations for location data
if (options.includeLoc) {
  feature.loc = calculateLocation(match);
}

Benefits:

  • Minimal garbage collection
  • Consistent memory usage
  • Better performance under load

Feature Detection Strategies

Simple Patterns

arrow_functions: /=>/,
template_literals: /`/,
optional_chaining: /\?\./,
nullish_coalescing: /\?\?/,

Complex Patterns

async_await: /\b(?:async\s+function|async\s*(?:\([^)]*\)|[a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>|await\s)/,
destructuring: /(?:const|let|var)\s*[[{]/,
private_fields: /#[a-zA-Z_$][a-zA-Z0-9_$]*/,
top_level_await: /^[^{]*\bawait\s/m

Pattern Categories

ES2015 Features:

  • Arrow functions, classes, template literals
  • Let/const, destructuring, spread/rest
  • For-of loops, generators, imports/exports

ES2020+ Features:

  • Optional chaining, nullish coalescing
  • Private fields, static blocks
  • Top-level await, logical assignment

Plugin Architecture

Plugins enable targeted detection for specific use cases:

ES2015 Plugin Example

ES2015 Plugin Implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

Custom Plugin Example

Custom React Hooks Plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

Using Plugins

// Use specific plugins for maximum performance
import { detectWithPlugins } from 'fast-brake';

// Single ES version - 85x faster!
const features = detectWithPlugins(code, ['es2015']);

// All ES versions
const features = detectWithPlugins(code, ['all']);

// Browser compatibility
const features = detectWithPlugins(code, ['browser:defaults']);

Plugin benefits:

  • Targeted detection: Load only what you need
  • Maximum performance: Single plugin can be 85x faster
  • Composable: Combine multiple plugins
  • Extensible: Create custom plugins

Plugin Performance Comparison

Plugin ConfigurationOps/secRelative SpeedUse Case
Single ES20151,063,49985.2xKnown target version
All ES Versions980,95478.6xComprehensive checking
Browser Defaults947,38175.9xBrowser compatibility
Full Detection12,4881.0xAll features, all versions

Error Handling Architecture

Detailed Error Information

const error = new Error(
  `ES feature "${feature.name}" requires ${feature.version} but target is ${options.target}` +
  (feature.line ? ` at line ${feature.line}:${feature.column}` : '') +
  (feature.snippet ? `\n  ${feature.snippet}` : '')
);

// Attach structured data
(error as any).feature = feature;
(error as any).target = options.target;

Extensibility Points

Adding New Features

  1. Add pattern to constants:
export const QUICK_PATTERNS = {
  // ... existing patterns
  new_feature: /pattern/,
};

export const FEATURE_VERSIONS = {
  // ... existing versions
  new_feature: 'es2025',
};
  1. Create your custom plugin:

See the Custom Plugin Example above for a complete implementation of a React Hooks detection plugin.

Custom Detection Logic

// Extend detector for custom features
class CustomDetector extends Detector {
  detect(code: string, options: DetectionOptions): DetectedFeature[] {
    const features = super.detect(code, options);
    
    // Add custom detection logic
    const customFeatures = this.detectCustomFeatures(code);
    
    return [...features, ...customFeatures];
  }
}

Performance Benchmarks

Live Benchmark Results

ParserTime (ms)Ops/secSpeed
fast-brake0.002552,3851.0x
fast-brake (detect)0.007139,0030.3x
fast-brake (es5 only)0.01664,1940.1x
fast-brake (browserlist)0.01663,2390.1x
cherow0.01953,4990.1x
fast-brake (es2015 only)0.02148,6910.1x
meriyah0.02147,3500.1x
esprima0.02637,9520.1x
acorn0.05418,5980.0x
@babel/parser0.05916,9190.0x
espree0.06415,7200.0x

Detailed Performance Analysis

Approach1000 FilesSingle FileMemory
fast-brake (plugin)1ms0.001ms2MB
fast-brake (all)80ms0.080ms4MB
Babel Parser~100ms~2ms~15MB
ESLint Parser~120ms~2.5ms~18MB
Acorn Parser~80ms~1.8ms~12MB

Results show performance with optimized plugins vs full detection.

Scalability Characteristics

graph LR
    A[File Size] --> B[Processing Time]
    B --> C[Linear Growth]
    
    D[Number of Files] --> E[Batch Processing]
    E --> F[Near-Linear Growth]
    
    G[Feature Complexity] --> H[Detection Time]
    H --> I[Constant Time]

Key Insights:

  • Linear scaling: Processing time scales linearly with code size
  • Batch efficiency: Minimal overhead for processing multiple files
  • Feature independence: Detection time independent of feature complexity
  • Memory stability: Consistent memory usage regardless of input size

Best Practices

Development Builds

// Development builds - use targeted plugins
const features = detectWithPlugins(code, ['es2015']);

// Hot reloading - fast feedback
if (checkWithPlugins(code, ['es2015'])) {
  // Continue with hot reload
}

Production Builds

// Production builds - comprehensive detection
const features = detectWithPlugins(code, ['all']);

// CI/CD pipelines - browser compatibility
const features = detectWithPlugins(code, ['all', 'browser:defaults']);

// Code analysis - with location data
const analysis = detect(codebase, { includeLoc: true });

Performance Optimization Tips

  1. Use targeted plugins:
// Development: targeted plugin
const devFeatures = detectWithPlugins(code, ['es2015']);

// Production: comprehensive detection
const prodFeatures = detectWithPlugins(code, ['all']);
  1. Reuse detector instances:
const detector = getDetector(); // Singleton
const results = files.map(file => detector.detect(file.content));
  1. Batch processing:
// Process multiple files efficiently
const results = files.map(file => ({
  file: file.path,
  features: detect(file.content, options)
}));

The fast-brake architecture demonstrates how optimized pattern matching and plugin architecture can deliver exceptional performance without sacrificing accuracy, making it the ideal choice for modern JavaScript tooling.