Direct eval() Disables VM Obfuscation
If a function contains a direct eval(code) call anywhere in its body (including in nested functions), that function is skipped by VM obfuscation and the obfuscator reports a VMDynamicCodeSkipped warning (naming the function when it has a name). In root mode (the default) the entire function and all its nested functions are skipped; in comment mode a nested function you mark separately is still virtualized unless it contains eval itself. A direct eval with a non-static argument also emits a DynamicCodeRenameRisk warning. This is because direct eval has access to the enclosing function's local variables, which are not available when the function is compiled to VM bytecode.
Important for IIFE-wrapped code. If a top-level IIFE contains any direct eval deep inside, the whole IIFE (including all your code) will not be VM-obfuscated.
Unwrapping the IIFE has a trade-off: once your functions sit at the top level, only the offending function is skipped, but the surviving functions are now root-level, so VM obfuscation preserves their names. See Hiding Function Names from LLM Analysis for how to keep those names out of the output.
Indirect forms like (0, eval)(code) and window.eval(code) do not block VM obfuscation. eval?.(code) is an exception: JavaScript runs it as indirect eval, but the obfuscator conservatively treats it as direct eval and skips the function.
The Function constructor (new Function(body) / Function(body)) is treated the same way when the body argument is dynamic. A function containing a dynamic new Function(...) call is also skipped, with a VMDynamicCodeSkipped warning. As with a dynamic direct eval, the obfuscator adds a DynamicCodeRenameRisk warning, because the runtime-built body may reference renamed identifiers. Fully static calls such as new Function('a', 'b', 'return a + b') are not skipped.
Indirect eval and the Function constructor execute in global scope. They cannot read the caller's local variables, but can still fail if they reference globals that were renamed or removed. A static body using only its own parameters, such as new Function('a', 'b', 'return a + b'), avoids that dependency. Review warnings and test the final bundle; changing eval syntax alone does not make arbitrary dynamic code safe.
Escape hatch (v6.14.0+): set vmForceCompileDynamicCode: true (or flip the Force Compile Dynamic Code switch under the VM section's Overrides group) to bytecode the surrounding function anyway and suppress VMDynamicCodeSkipped. It cannot repair scope: inside a force-compiled function, direct eval cannot read or write the function's local variables, its parameters, or the variables of a virtualized enclosing function, even when the code is a string literal. Use it only when the evaluated code references nothing but globals. DynamicCodeRenameRisk keeps firing with this option on, because the rename risk it describes is independent of the VM skip.
See VM Obfuscation with eval and new Function for the full matrix, the warning shapes, and workarounds.
