Skip to main content

Overview

The RefractorEngine class orchestrates the full compile → obfuscate → compile pipeline. It’s a pure engine-layer class that depends on abstract Compiler and KernelIO interfaces, allowing you to provide custom IO-layer implementations.

Constructor

RefractorEngine({
  required Compiler compiler,
  required KernelIO kernelIO,
  Logger? logger,
})
compiler
Compiler
required
Implementation of the Compiler interface for compiling Dart source to kernel and to target formats
kernelIO
KernelIO
required
Implementation of the KernelIO interface for loading and writing kernel .dill files
logger
Logger?
Optional Mason logger for detailed build progress messages

Methods

run()

Executes the complete obfuscation pipeline: compile source to kernel, run obfuscation passes, write obfuscated kernel, and compile to target format.
Result<BuildResult> run({
  required RefractorConfig config,
  required BuildRequest request,
})
config
RefractorConfig
required
Configuration object specifying which passes to enable and their options
request
BuildRequest
required
Build parameters including input/output paths, target format, and work directory
Result<BuildResult>
Result<BuildResult>
Returns Ok(BuildResult) on success, containing output path, symbol table, and list of passes run

Supporting Classes

BuildRequest

Bundles the IO parameters for a RefractorEngine.run() invocation.
class BuildRequest {
  const BuildRequest({
    required String input,
    required String output,
    required Target target,
    required String workDirectory,
  });
}
input
String
required
Path to the Dart entry point file (e.g., lib/main.dart)
output
String
required
Path where the final compiled output should be written
target
Target
required
Compilation target: Target.exe, Target.aot, Target.jit, or Target.kernel
workDirectory
String
required
Directory for intermediate build artifacts (e.g., .dart_tool/refractor)

BuildResult

Result of a successful RefractorEngine.run() invocation.
class BuildResult {
  BuildResult({
    required String outputPath,
    required SymbolTable symbolTable,
    required List<String> passesRun,
  });
}
outputPath
String
The final output path where the compiled artifact was written
symbolTable
SymbolTable
Symbol table containing mappings from original to obfuscated identifiers
passesRun
List<String>
Names of all obfuscation passes that were executed

Target

Enum representing valid compilation targets.
enum Target {
  exe,      // Native executable
  aot,      // AOT snapshot
  jit,      // JIT snapshot  
  kernel,   // Kernel .dill file
}

Usage Example

import 'package:refractor/refractor.dart';

void main() {
  final engine = RefractorEngine(
    compiler: DartCompiler(),
    kernelIO: FileKernelIO(),
  );

  final result = engine.run(
    config: RefractorConfig(
      passes: [RenamePass(), StringEncryptPass()],
    ),
    request: BuildRequest(
      input: 'lib/main.dart',
      output: 'build/out',
      target: Target.exe,
      workDirectory: '.dart_tool/refractor',
    ),
  );

  result.when(
    ok: (buildResult) {
      print('Build complete: ${buildResult.outputPath}');
      print('Passes run: ${buildResult.passesRun}');
      print('Symbols mapped: ${buildResult.symbolTable.size}');
    },
    err: (error) => print('Build failed: $error'),
  );
}
The engine handles the complete pipeline automatically:
  1. Compiles source to kernel .dill
  2. Loads kernel and runs obfuscation passes
  3. Writes obfuscated kernel
  4. Compiles to final target format (or outputs .dill for kernel target)
For Target.kernel, the engine writes the obfuscated .dill directly and skips the final compileToTarget step.

PassRunner

Orchestrates obfuscation passes over kernel components

SymbolTable

Tracks identifier mappings for deobfuscation

Build docs developers (and LLMs) love