Opt-In Software Blog

renamedecl

🔄 Renaming Variables and Functions in JavaScript Using ASTs

When working with JavaScript, there are times you might want to automatically rename variables or functions across your code — perhaps for obfuscation, code transformation, or refactoring. Doing this safely, without accidentally breaking your program, requires understanding how your code is structured — and that’s where the Abstract Syntax Tree (AST) comes in.

In this post, we’ll look at how to rename variable and function declarations using ASTs, with a simple utility renamedecl.


🌳 What Is an AST?

An Abstract Syntax Tree (AST) is a structured, tree-like representation of your source code.
Instead of dealing with raw text, you work with objects that represent program constructs like variables, functions, loops, and expressions.

For example, the code:

const x = 5;
console.log(x);

can be represented (simplified) as:

{
  type: "Program",
  body: [
    {
      type: "VariableDeclaration",
      declarations: [
        {
          type: "VariableDeclarator",
          id: { type: "Identifier", name: "x" },
          init: { type: "Literal", value: 5 }
        }
      ]
    },
    {
      type: "ExpressionStatement",
      expression: {
        type: "CallExpression",
        callee: {
          object: { name: "console" },
          property: { name: "log" }
        },
        arguments: [{ type: "Identifier", name: "x" }]
      }
    }
  ]
}

By working with this structure, you can programmatically modify parts of your code (e.g. change x to width) and then regenerate valid JavaScript source code.


🧩 Tools: Acorn, Escodegen

  • Acorn — a fast, lightweight JavaScript parser. It converts JS source code into an AST.
  • Escodegen — generates readable JavaScript code from an AST.

Scopes

Scopes — just like in real code, variables and functions in an AST exist within scopes (e.g., global, function, block). When renaming identifiers, you need to make sure you don’t accidentally rename a variable from an outer scope that has the same name.


🚀 Introducing renamedecl

renamedecl is the lightweight tool for renaming variables and functions in JS code based on an AST.

The function renameDeclarations(ast, rename, initscope?) walks through your AST, finds all declarations (variables, function names, parameters, etc.), and lets you rename them safely according to the rules you define.

It can be used in two main ways:


1. Automatic Renaming

You can rename every variable and function in a consistent way — for example, to obfuscate or anonymize code.

const acorn = require('acorn');
const escodegen = require('escodegen');
const { renameDeclarations } = require('renamedecl');

const originalCode = `
function add(x, y) {
    const result = x + y;
    return result;
}
`;

const ast = acorn.parse(originalCode, {
    ecmaVersion: 2020,
    sourceType: 'script'
});

// Rename all identifiers sequentially
renameDeclarations(
    ast,
    (id, scope) => `v${++scope.varNum}`,
    scope => { scope.varNum = 0; }
);

const newCode = escodegen.generate(ast);
console.log(newCode);

Output:

function v1(v2, v3) {
    const v1 = v2 + v3;
    return v1;
}

Here, every declared identifier got renamed with a consistent numbering scheme, respecting the correct scope hierarchy.


2. Custom Rename Mapping

You can also define your own rename map to transform specific variable or function names.

const renameMap = {
    x: 'width',
    y: 'height',
    result: 'sum'
};

renameDeclarations(ast, id => renameMap[id.name]);

This is great for refactoring, such as renaming variables to more meaningful names.


🧠 How Scoping Works

renamedecl automatically tracks scopes as it traverses the AST.
When it enters a new function or block, it creates a new scope object.
This ensures that two variables named x in different functions don’t get mixed up:

function outer() {
    const x = 10;
    function inner() {
        const x = 20;
        console.log(x);
    }
    inner();
}

Both x variables live in different scopes. The renaming logic keeps that distinction intact — so each gets its own renamed version.


🔧 Why Use This?

  • Safe — Respects JavaScript scoping rules
  • 🔍 Customizable — You control the renaming logic
  • 🧰 Tool-friendly — Works directly with standard AST tools
  • ⚙️ Flexible — Use it for obfuscation, refactoring, or static analysis

🧩 Try It Out

You can install it via npm:

npm install git+https://github.com/optinsoft/renamedecl.git

Then import and use it as shown above.


💡 Conclusion

Working with ASTs may sound intimidating at first, but with tools like Acorn, Escodegen, and utilities such as renamedecl, transforming JavaScript code becomes powerful and approachable.

By controlling variable and function names at the AST level, you can safely build tools for code analysis, transpilation, refactoring, or obfuscation — all while preserving the correctness of your original code.

How to download a Chrome extension without installing it

  1. In the Chrome Web Store, find the extension you need, for example, uBlock Origin.
  2. The extension’s URL looks like this: https://chromewebstore.google.com/detail/ublock/epcnnfbjfcgphgdmggkamkmgojdagdnn?hl=en-US&utm_source=ext_sidebar. The part epcnnfbjfcgphgdmggkamkmgojdagdnn is the extension’s unique ID.
  3. Find out your version of Chrome, for example, 141.0.7390.55.
  4. Use CURL to get the extension’s download link, replacing the extension ID (epcnnfbjfcgphgdmggkamkmgojdagdnn) and Chrome version (141.0.7390.55) with your own values:
    curl "https://clients2.google.com/service/update2/crx?response=redirect&os=win&arch=x64&os_arch=x86_64&prod=chromecrx&prodchannel=&prodversion=141.0.7390.55&lang=en-US&acceptformat=crx3,puff&x=id%3Depcnnfbjfcgphgdmggkamkmgojdagdnn%26installsource%3Dondemand%26uc&authuser=0"
  5. The result of the previous CURL command will look something like this:
    <HTML>
    <HEAD>
    <TITLE>Moved Temporarily</TITLE>
    </HEAD>
    <BODY BGCOLOR="#FFFFFF" TEXT="#000000">
    <!-- GSE Default Error -->
    <H1>Moved Temporarily</H1>
    The document has moved <A HREF="https://clients2.googleusercontent.com/crx/blobs/AcLY-yQ8Sxe7u0UiOxVYs1X2QxXnl4NGRAS6t4jJr_viP7fvXl9ARlV4ETIu1woz6O7cdB3-RBD9cYdV3APCdHY8S6kBmmk5mSnRTo0LZ8FUJQEkbk_6NnrX0EPLsAaqxNK-AMZSmuUQPLnhgEjCRn4So0hrUrRuyQSHOA/EPCNNFBJFCGPHGDMGGKAMKMGOJDAGDNN_25_5_0_0.crx?authuser=0">here</A>.
    </BODY>
    </HTML>
    The URL from which you can download the extension is: https://clients2.googleusercontent.com/crx/blobs/AcLY-yQ8Sxe7u0UiOxVYs1X2QxXnl4NGRAS6t4jJr_viP7fvXl9ARlV4ETIu1woz6O7cdB3-RBD9cYdV3APCdHY8S6kBmmk5mSnRTo0LZ8FUJQEkbk_6NnrX0EPLsAaqxNK-AMZSmuUQPLnhgEjCRn4So0hrUrRuyQSHOA/EPCNNFBJFCGPHGDMGGKAMKMGOJDAGDNN_25_5_0_0.crx?authuser=0
  6. Use CURL to download the CRX file:
    curl "https://clients2.googleusercontent.com/crx/blobs/AcLY-yQ8Sxe7u0UiOxVYs1X2QxXnl4NGRAS6t4jJr_viP7fvXl9ARlV4ETIu1woz6O7cdB3-RBD9cYdV3APCdHY8S6kBmmk5mSnRTo0LZ8FUJQEkbk_6NnrX0EPLsAaqxNK-AMZSmuUQPLnhgEjCRn4So0hrUrRuyQSHOA/EPCNNFBJFCGPHGDMGGKAMKMGOJDAGDNN_25_5_0_0.crx?authuser=0" --output uBlock.crx

Git Deployer

I wrote a python module Git Deployer. It allows me to automate the deployment of generated static sites (documentation, help guides, etc.) using Git.

My use case

I’m using Sphinx to generate documentation. And I need to deploy the generated static files from _build/html to my server.

On the server side I have created ‘bare’ Git repo with post-receive hook:

#!/bin/sh
GIT_WORK_TREE=/var/www/my_domain/html/help git checkout -f main.

When I push to this repo, it automatically deploys to a website folder.

I’m working in VS Code. I’ve installed Git Deployer with pip:

python -m pip install git+https://github.com/optinsoft/git-deployer.git

In the project’s folder I’ve created deploy_config.yml:

deploy:
  remote:
    name: 'myserver' 
    url: 'ssh://user@myserver/~/help.git'
  branch: 'master'
  name: owner_name
  email: owner@email
  message: 'new commit at %Y-%m-%d %H:%M:%S'
  git_init: True
  force_push: True

Now I can deploy _build/html with a single command:

deploy _build/html

gen_eth and gen_trx updates

After installing the NVIDIA GPU Computing Toolkit v13, the gen_eth and gen_trx projects started producing an error:

ImportError: DLL load failed while importing _driver: DLL load failed

The reason is that pycuda is trying to load the CUDA DLL from the bin directory:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\bin

I am using the latest version of pycuda available at the moment: v2025.1.2.

pycuda\driver.py:

def _add_cuda_libdir_to_dll_path():
from os.path import dirname, join

text
cuda_path = os.environ.get("CUDA_PATH")

if cuda_path is not None:
    os.add_dll_directory(join(cuda_path, "bin"))
    return

However, in version v13 of the NVIDIA GPU Computing Toolkit, the DLLs are located in the bin\x64 directory:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\bin\x64

To solve this problem, a new setting CUDA_DLL_PATH has been added to settings.ini, which contains the full path to the CUDA DLL.

settings.ini:

[settings]
CL_PATH=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\x64
CUDA_DLL_PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\bin\x64

The latest versions of gen_eth and gen_trx are available on GitHub:

PS. If the following error occurs:

pycuda._driver.LogicError: cuModuleLoadDataEx failed: device kernel image is invalid

then you need to update the NVIDIA video driver: https://www.nvidia.com/en-us/drivers/

Blog migrated to Hexo

This blog has been migrated from WordPress to Hexo.

For the blog migration, I wrote a powershell script called wp-hexo-convertor, which is available on GitHub.

Prior to migration, the WordPress blog was converted to a static version. The wp-hexo-convertor utility was then used to generate posts and redirect pages for Hexo. These redirects are essential to prevent the loss of organic traffic from Google search.

The redirects are implemented via the hexo-generator-alias plugin. I created a GitHub fork that uses the url_for function instead of full_url_for.

Opt-In List Manager 1.6.105

by Vitaly, Thursday, March 19th, 2020

Version 1.6.105 of the Opt-In List Manager has been released.

What’s New

Extract And Clean

  1. Clean Mail Lists: Remove empty fields (columns).
  2. Clean Mail Lists: Custom field (column) delimiters.
  3. Clean Mail Lists: The number of output columns. If the source row contains less than the specified number of columns, the list manager will add missing columns (blank). If the source row contains more than the specified number of columns, the list manager will cut extra columns.

Merge E-Mail Lists

  1. Keep Email Duplicates (remove full duplicates only).

Misc. Utilites

  1. Replace blanks with the specified text.
  2. Replace the matched regular expression pattern with the specified text.
  3. You can specify field (column) numbers to modify (add prefix, suffix or replace the text).
  4. Calculate SHA1, SHA-256 and SHA-512 hash values.

Websites Loader 1.21

by Vitaly, Monday, December 16th, 2019

Version 1.21 of the Websites Loader 1.21 released.

What’s New

Replace Rules has been added. Replace rule applies to HTML content and allows, for example, replace one domain by another.

Each rule consist of the pattern, which is regular expression, and the replacement value. Matching text will be replaced with the replacement value.

Replacement value can contain references to matching groups. Example:

Pattern: (https?://)?(localhost/)
Replacement value: $2
Subject: http://localhost/aaa
Result: localhost/aaa

Tags: load, Regular Expression, website