Skip to content

Appears to be a scope resolution bug #1386

Closed

Description

@z0ffy

Expected Behavior

The obfuscated output should preserve the original binding semantics.

A semantically correct result would be equivalent to:

import { i as _imp } from './runtime.js';

function factory() {
  return 'factory-result';
}

var P = class _cls {
  static instance;

  static getInstance() {
    return _cls.instance ||= new _cls(), _cls.instance;
  }
};

var x = _imp(factory(), 1);

export { P, x };

or:

import { i as _imp } from './runtime.js';

function factory() {
  return 'factory-result';
}

var _P = class {
  static instance;

  static getInstance() {
    return _P.instance ||= new _P(), _P.instance;
  }
};

var x = _imp(factory(), 1);

export { _P as P, x };

Current Behavior

The obfuscated output rewrites the class self-reference to the imported binding.

It becomes effectively:

import { i as _0x48e620 } from './runtime.js';

function factory() {
    return 'factory-result';
}

var P = class e {
    static ['instance'];
    static ['getInstance']() {
        return _0x48e620['instance'] ||= new _0x48e620(), _0x48e620['instance'];
    }
};

var x = _0x48e620(factory(), 0x1);

export { P, x };

This is incorrect because _0x48e620 is the imported binding, not the class.

If the imported binding is a function or arrow function, runtime execution fails with:

TypeError: function is not a constructor

Steps to Reproduce

  1. Open https://obfuscator.io/legacy-playground
  2. Paste runtime.js and the main module code below into the editor
  3. Use the obfuscator options listed below
  4. Run obfuscation
  5. Inspect the generated getInstance() method
  6. Notice that the class self-reference is rewritten to the imported binding

JavaScript Obfuscator Edition

Your Environment

  • javascript-obfuscator: 4.2.2
    • Also reproduced after testing newer versions, including 5.3.0
  • Node.js: 20.x
  • OS: macOS

Stack trace

Minimal working example that will help to reproduce issue

// runtime.js
export const i = (value, flag) => ({ value, flag });
import { i as e } from './runtime.js';

function factory() {
  return 'factory-result';
}

var P = class e {
  static instance;

  static getInstance() {
    return e.instance ||= new e(), e.instance;
  }
};

var x = e(factory(), 1);

export { P, x };

Activity

  1. sanex3339 commented on Mar 21, 2026

    @sanex3339
    Member

    Released as 5.3.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions