What survives

Does obfuscation change object key order?

Key order sounds like an implementation detail until something signs a JSON document, compares a snapshot, or hashes a serialised payload. Then it becomes load bearing. The measured answer is that protection does not touch it, in either target version, and the reason is structural rather than lucky.

Key order is specified, not incidental

JavaScript objects have a defined enumeration order, and it is not simply the order you typed. Integer-like keys come first, in ascending numeric order, regardless of when they were inserted. Every other string key follows in insertion order. Deleting a key and adding it back moves it to the end, because that is a new insertion.

This matters because a lot of production code depends on it without saying so. Canonical JSON signing depends on it. Snapshot tests that compare serialised output depend on it. Wire formats where a receiver reads fields positionally depend on it. A transform that quietly reordered object literals would break all of those in a way that passes every unit test that checks values rather than bytes.

What was measured

An object was built to exercise every rule at once: string keys inserted out of alphabetical order, two integer-like keys ("10" and "2") inserted between them, a key added after construction, and one key deleted and then re-added. Then Object.keys, for...in, Object.getOwnPropertyNames and JSON.stringify were all read off it.

The original produced 2,10,zebra,mango,banana,apple from all four, with apple at the end because it had been deleted and re-added, and the integers ahead of everything else in numeric rather than insertion order.

The protected build produced the same string from all four, on the ES5 target and on the modern target. A nested object literal kept its inner order too. Nothing moved.

Why it holds

The reason is worth understanding, because it tells you how far the guarantee extends. Object literals are rewritten by the transform, but they are rewritten in place: properties keep their positions in the literal, and the engine does not sort, group or deduplicate them. Order comes out unchanged because nothing in the pipeline has a reason to change it.

That also means the guarantee is about ORDER, not about NAMES. Order is preserved unconditionally. Names are preserved unless you opt into member renaming, which is a separate switch that requires an explicit regexp or mapping before it will run at all.

So with member renaming on, a serialised payload keeps its field ORDER and loses its field NAMES: the second field is still the second field, but it is called something else. If a receiver parses positionally that survives and if it parses by name it does not, which is the ordinary member-renaming trade rather than an ordering problem.

The cases that still deserve a test

Preserved ordering is a strong result but it is not a licence to stop checking, because the things that depend on order usually depend on more than order. A canonical-JSON signature depends on key order AND key names AND number formatting AND string escaping. Protection leaves the first alone and can change the second if you configure it to.

The practical test is direct: serialise a representative object in a protected build, serialise it in an unprotected build, and compare the two strings byte for byte. If they match, everything downstream that consumes those bytes is safe. If they differ, the diff shows you immediately whether you are looking at reordering (you are not, on the measurement above) or renaming (you probably are).

Snapshot tests are the cheapest existing place to run that check, because they already compare serialised output byte for byte and already fail loudly. Running the suite against a protected build is the whole test.

Frequently asked questions

Does obfuscation reorder object properties?

No. Measured by running the engine and comparing enumeration output, Object.keys, for...in, Object.getOwnPropertyNames and JSON.stringify all produce the same order before and after protection, on both the ES5 and the modern target.

Are integer-like keys still enumerated first?

Yes. The specified rule that integer-like keys come first in ascending numeric order, ahead of string keys in insertion order, is unchanged by protection. A test object with keys "10" and "2" enumerated them as 2 then 10 in both builds.

Does a deleted and re-added key still move to the end?

Yes. That behaviour comes from the language, not from the source text, and the protected build reproduced it exactly.

Is JSON.stringify field order stable after obfuscation?

Field order is stable. Field names are stable too unless you opt into member renaming, which is a separate switch that requires an explicit regexp or mapping. With it on, the order holds but the names change.

Will canonical JSON signing still work?

Ordering will not be what breaks it. Compare a serialised sample from a protected build against one from an unprotected build byte for byte; if they differ, the cause is member renaming or another configured transform rather than reordering.

Do nested objects keep their order?

Yes. A nested object literal kept its inner key order in the measured build, on both targets.

Related reading