These two options decide which JavaScript your protected file is written in. They are not protection levels: everything you enabled still runs, and the same code is still obfuscated. They only choose the syntax it comes out as.
TargetVersion
es5 (default) — ES2015+ syntax is down-levelled, so classes, arrow functions, destructuring, template literals and for-of become code a pre-ES2015 engine can run.
modern — the down-levelling pass is skipped and the output keeps the syntax your source used. Choose this when the file is served to current browsers or run on Node.js.
If you already build with Babel, TypeScript or a bundler target, the decision is made there: set this to match what your build emits, and the protected file will not reintroduce syntax your toolchain deliberately removed.
DownlevelIteration
Only meaningful on the es5 target. Off by default, it opts into a spec-faithful for-of lowering: the iterable is stepped lazily, and the iterator’s return() hook runs on break, on throw, and on an early return — the same trade TypeScript exposes as --downlevelIteration.
The default lowering reads the iterable by index, which is the faster shape for an array and measurably so — the per-step iterator protocol call costs several times more on the case almost every loop actually iterates. The price is that a non-array iterable is drained before the loop body runs, so per-step side effects all fire and break does not stop them.
Turn it on when you iterate a generator, a stream, or any iterator whose steps have effects and where stopping early matters. Leave it off when your for-of loops run over arrays, which is the overwhelmingly common case. On modern it changes nothing, because native for-of is kept as written.
Setting it
Online tool. Two options in the feature list, badged Output: Modern Output (ES2015+) and Spec-Faithful for-of (ES5). Both are off unless you switch them on, and neither is included in the Maximum preset — a preset that means “more protection” must not silently change the JavaScript your users receive.
npm package (jso-protector 0.4.0+), in jso.config.json:
{
"preset": "balanced",
"targetVersion": "modern"
}
or on the command line:
jso-protector --option TargetVersion=modern
jso-protector --option DownlevelIteration=True
API requests carry the option by name: set TargetVersion and DownlevelIteration alongside your other options. See npm options for the full option surface.
The desktop app does not expose these two in its options dialog yet. Until it does, protect with the npm package or the API when you need a target other than the es5 default.
What to check after switching
- Moving to
modern: confirm the oldest engine you support really does handle ES2015+. The protected file will contain the same syntax family your source did.
- Staying on
es5: if any for-of in your code iterates something other than an array, decide whether laziness matters to it, and turn on DownlevelIteration if it does.
- Either way: run your own test suite against the protected build. That is the check that catches everything, and it is the one we recommend regardless of options.
Frequently asked questions
Does the output target change how strongly my code is protected?
No. TargetVersion and DownlevelIteration choose which JavaScript the protected file is written in; every protection option you enabled runs either way. That is why the online tool badges them Output rather than listing them among the protection toggles, and why the Maximum preset does not switch them on.
Which target should I use?
Use modern when the file is served to current browsers or run on Node.js, which is the common case for an app that already ships through a bundler. Use es5, the default, when the protected file has to run on a pre-ES2015 engine, such as an embedded WebView or an old kiosk browser. If you already run Babel or TypeScript, they have decided this for you, and the protected file only needs to match what they emit.
What does DownlevelIteration change?
On the es5 target it makes for-of lowering spec-faithful: the iterable is stepped lazily and the iterator’s return hook runs on break, throw, and early return. The default lowering reads an array by index, which is faster but drains a non-array iterable before the loop body runs. It has no effect when TargetVersion is modern, because a modern target keeps native for-of.
When does the difference actually matter?
When you iterate something that is not an array and stopping early matters: a generator, a stream reader, or any iterator with side effects per step. Over a plain array the two lowerings produce the same values, which is why the faster one is the default.
Where can I set the output target?
In the online tool as the Modern Output and Spec-Faithful for-of options, in jso-protector 0.4.0 or later as targetVersion and downlevelIteration in jso.config.json, and in API requests as TargetVersion and DownlevelIteration. The desktop app does not expose them in its options dialog yet.