Parallel-Aware Scope Analysis (PASA)
- Parallel-Aware Scope Analysis (PASA) is a static analysis technique that extracts lexical scopes and cross-file dependencies in large JavaScript codebases.
- It partitions code into independent units, enabling multi-core processing and safe, localized identifier renaming without violating JavaScript semantics.
- PASA’s approach reduces code inflation and memory overhead while ensuring 100% semantic preservation, significantly outperforming traditional sequential obfuscators.
Searching arXiv for the cited papers to ground the article in current records. arXiv query: (Li et al., 29 Sep 2025) JSProtect Parallel-Aware Scope Analysis Parallel-Aware Scope Analysis (PASA) is a scope- and dependency-aware static analysis introduced as the central analysis layer of JSProtect, a scalable obfuscation framework for large WeChat mini-games and other industrial-scale JavaScript codebases. Its purpose is to build a detailed view of lexical scopes, identifier resolution, and cross-file dependencies so that obfuscation can be performed safely, in parallel, and with aggressive identifier reuse. In JSProtect, PASA is the foundation that enables two coupled optimizations: independent code partitioning for multi-core processing and independent namespace management that reuses short identifiers without violating JavaScript’s lexical resolution rules (Li et al., 29 Sep 2025).
1. Conceptual role and motivation
PASA was introduced to address three failure modes that the JSProtect paper attributes to existing JavaScript obfuscation tools at industrial scale. First, they are too slow: processing time grows super-linearly with code size, and the paper reports tools taking over 13 hours on a 20 MB codebase. Second, they consume too much memory, with some tools reaching 22 GB on 20 MB inputs. Third, they bloat code severely: traditional obfuscators can inflate code by 10–20×, partly because they inject dead code, flatten control flow, unroll loops, and exhaust short identifiers before falling back to long generated names such as random hex strings (Li et al., 29 Sep 2025).
Within this formulation, PASA is not itself an obfuscation transform. It is the analysis substrate that makes the rest of the framework possible. Traditional obfuscators often rely on a global analysis of the whole program, which creates unavoidable dependencies between transformations and forces a sequential workflow. PASA instead computes enough scope information to determine which code regions are independent, which identifiers can be renamed locally without conflicts, where cross-file or cross-scope dependencies require coordination, and where code can be split into independent units for parallel execution.
A common misconception is that parallelization alone explains JSProtect’s scalability. The paper’s stronger claim is that scope analysis is the key to solving both scalability and size inflation. If the system knows which scopes are independent, it can process them in parallel and rename identifiers independently in each scope, reusing short names aggressively. This makes PASA simultaneously a concurrency-enabling analysis and a code-size control mechanism.
2. Formal model of scopes, dependencies, and resolution
The paper models a JavaScript program as
where is the set of source files, is the dependency graph among files, and is the execution environment. PASA then builds a scope tree
where is the set of scope nodes, is lexical nesting, and is the global scope (Li et al., 29 Sep 2025).
Each scope stores four kinds of information: , 0, 1, and 2, which flags dynamic features like eval and with. This representation is central because PASA’s later partitioning and renaming decisions depend on exact knowledge of declaration sites, reference sites, lexical ancestry, and dynamic-scope hazards.
Identifier resolution is defined recursively as
3
This resolution function is crucial because PASA uses it to decide when a name can be safely reused. The analysis is therefore “parallel-aware” only because it is also scope-aware: partitioning and renaming are constrained by the same lexical-resolution semantics that define ordinary JavaScript name lookup.
3. Placement within the JSProtect workflow
The workflow described in the paper is: parsing and dependency extraction; PASA scope analysis; partitioning and namespace planning; parallel obfuscation of independent units; lightweight coordination for cross-boundary cases; and reassembly. PASA sits in the middle and produces two explicit outputs: a Scope Independence Map and Dependency Boundary Markers (Li et al., 29 Sep 2025).
| PASA output | Immediate use | Effect |
|---|---|---|
| Scope Independence Map | Partitioning and namespace planning | Enables independent processing |
| Dependency Boundary Markers | Cross-boundary coordination | Limits required synchronization |
The analysis pipeline is described as a multi-phase parallel analysis architecture. During simultaneous parsing and dependency extraction, PASA extracts import/export relations, global variable references, and cross-file function calls. This produces a dependency graph
4
where 5 is the set of files and 6 is the set of file dependencies.
The next phase partitions files or regions with minimal cross-dependencies. The paper states that graph partitioning is used to minimize edge cuts in 7. The stated rationale is that most scope relationships then remain intra-file, which are much cheaper to analyze and transform independently. The final phase performs lightweight cross-file resolution: only identifiers and bindings that cross partitions require coordination, reducing the expensive global synchronization that would otherwise undermine parallel performance.
This organization clarifies PASA’s architectural position. It is neither a purely local AST pass nor a whole-program monolith. It is a static analysis layer that computes just enough global structure to support mostly local transformation.
4. Independent code partitioning for multi-core obfuscation
One of PASA’s two major optimizations is independent code partitioning. The design principle is that a code segment can be obfuscated independently if its internal identifiers resolve locally, or if all outside dependencies are already known. The paper defines an independent code unit 8 using three properties: self-containment, independence, and boundary clarity. The boundaries are determined by PASA’s dependency boundary markers (Li et al., 29 Sep 2025).
For each independent unit, PASA pre-computes external dependencies as metadata. Worker threads then process different units in parallel. The paper further states that obfuscation can happen as direct code-to-code transformation, not necessarily whole-program AST rewriting. Units are reassembled afterward using the preserved file and structure information.
The significance of this design is operational rather than merely descriptive. Traditional obfuscators incur a sequential bottleneck because they rely on a single global pass over the entire program. PASA replaces that structure with parallel processing of partitions, which the paper describes as producing near-linear scaling with CPU cores. In the evaluation, JSProtect processes 20 MB codebases in minutes; specifically, a 20 MB input takes 141 seconds, whereas JS-Obfuscator takes over 47,445 seconds.
A further implication of the partitioning strategy is that “parallel-aware” does not mean arbitrary sharding. PASA’s partitions are derived from lexical and dependency constraints, not from coarse file-level batching alone. This suggests that its scalability depends on the correctness of its boundary analysis as much as on the number of worker threads.
5. Independent namespace management and semantic preservation
The second major optimization enabled by PASA is independent namespace management. The problem it addresses is global renaming pressure: when an obfuscator maintains a single identifier namespace, short names such as a, b, and c are exhausted, and later variables receive long generated names, which substantially inflates output size. PASA solves this by proving which scopes are independent, allowing JSProtect to treat each function scope or independent region as its own namespace (Li et al., 29 Sep 2025).
The paper defines a safe renaming function
9
and states that it is safe if
0
This condition formalizes the central idea: if two identifiers refer to different declarations, they may share the same renamed identifier provided scope resolution remains correct.
The renaming strategy proceeds by using PASA to obtain independent partitions, processing those partitions in parallel, traversing scopes in topological order within each partition, building a forbidden set from ancestor-visible identifiers, choosing the shortest available names from the pool
1
and preserving names in dynamic scopes such as eval and with. The paper’s algorithmic sketch, titled PASA-Enabled Scope-Aware Identifier Renaming, initializes a mapping 2, iterates over each independent partition in parallel, computes forbidden names from ancestors, computes available names 3, assigns the shortest available names to declarations, and preserves identifiers in dynamic scopes.
The correctness claim is explicit. The paper states that the renaming algorithm is safe and preserves program semantics under PASA’s independence guarantees, with a proof by induction on scope depth. The base case handles root scopes with precomputed cross-partition constraints; the inductive case uses the forbidden set to ensure that ancestor-visible names remain correctly resolved. Parallel execution is safe because partitions are independent, so no cross-partition semantic interference occurs. In the reported evaluation, semantic equivalence is confirmed at 100% across Test262, engines, mini-games, and libraries.
This section also resolves another common misunderstanding: aggressive short-name reuse is not presented as a heuristic shortcut. It is presented as a semantics-preserving consequence of precise lexical-resolution analysis.
6. Empirical behavior, baseline comparison, and security effects
The empirical results attributed to PASA concern both throughput and output quality. On 20 MB inputs, the paper reports that JSProtect can process codebases in minutes, with 141 seconds in the evaluation. Code size inflation is reported as 23.9 MB, or 20%, on a 20 MB input, compared with 239.5 MB, or 1098%, for JS-Obfuscator. The baseline tools discussed are JS-Obfuscator, JsJiaMi, VirBox Protector, and JScrambler (Li et al., 29 Sep 2025).
The paper characterizes these baselines as suffering from sequential processing, global renaming pressure, namespace exhaustion, large code inflation, and runtime overhead from heavy transformations. Against that background, PASA’s two enabling ideas—partitioning the workload and localizing namespace management—are directly tied to much better scalability, much lower code inflation, 100% semantic equivalence, better runtime behavior, and stronger resistance to analysis.
Runtime behavior is reported as near-native. The paper gives the following examples: PixiJS runs at 60 FPS versus the original 60 FPS; JSZip runs in 8.1 s versus the original 7.9 s; and mini-games run at 35 FPS versus the original 45 FPS, which is reported as much better than baselines that can drop to 1–9 FPS. PASA is described as supporting runtime performance indirectly by enabling lightweight transformation choices within safe units and by allowing memoization or guard-variable insertion per partition.
The security evaluation is summarized at a high level rather than through a single formal metric. The paper states that JSProtect provides superior security effectiveness against both static analysis tools and LLMs. It also reports higher cyclomatic complexity and NID, together with reduced LLM prediction accuracy. A plausible implication is that PASA’s contribution to security is not only that it permits obfuscation at scale, but that it permits a different balance between transformation strength and operational overhead.
7. Relation to broader parallel-aware analysis research
PASA in JSProtect is a JavaScript obfuscation analysis centered on lexical scopes and namespace reuse. A plausible implication is that it belongs to a broader methodological family in which scalability is obtained by structured decomposition rather than by monolithic whole-program processing. Two adjacent lines of work illustrate this broader pattern.
In software verification, explicit splitting of a program’s execution space into path ranges has been proposed so that arbitrary analyses can run on different ranges in parallel. That framework operates by split, analyze in parallel, and join; it supports heterogeneous ranged analyses, implements range reduction in CPAchecker, orchestrates execution in CoVeriTeam, and introduces work stealing between analyses so that a finished analysis is restarted on the remaining range unless it has already found a violation (Haltermanna et al., 2024). The strongest practical result reported there is that work stealing turns ranged analysis from a promising decomposition into an effective verification strategy, while adding no additional incorrect answers. This does not make path-range analysis identical to PASA, but it reinforces the general idea that careful decomposition plus limited coordination can outperform raw portfolio parallelism.
In parallel complexity analysis for asynchronous message-passing programs, temporal session types provide a local, compositional discipline for rate, latency, response time, and span. That framework enriches binary session types with the temporal modalities 4, 5, and 6, proves soundness by progress and type preservation using a timed multiset rewriting semantics, and analyzes representative cases such as bit-stream rates, queue response time, and fork/join span (Das et al., 2018). Here again, the connection is methodological rather than terminological: locality and compositionality are used to reason about parallel behavior without recovering a single global dependence structure.
Taken together, these adjacent results suggest that PASA is best understood not only as a JavaScript-specific engineering mechanism, but also as an instance of a broader research pattern: identify the boundaries that matter for correctness, exploit independence aggressively within those boundaries, and reserve coordination for the comparatively small set of cross-boundary cases.