mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Fixed NodeUtils.cloneRecursive corrupting range property when cloning AST nodes, causing scope analysis to incorrectly resolve destructuring default parameter references
This commit is contained in:
@@ -122,6 +122,11 @@ export class NodeUtils {
|
||||
return node;
|
||||
}
|
||||
|
||||
// Handle primitives directly - don't try to clone them as objects
|
||||
if (typeof node !== 'object') {
|
||||
return node;
|
||||
}
|
||||
|
||||
const copy: Partial<T> = {};
|
||||
const nodeKeys: (keyof T)[] = <(keyof T)[]>Object.keys(node);
|
||||
|
||||
|
||||
+83
@@ -3,6 +3,7 @@ import { assert } from 'chai';
|
||||
import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
|
||||
|
||||
import { readFileAsString } from '../../../../helpers/readFileAsString';
|
||||
import { evalLocal } from '../../../../helpers/evalLocal';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade';
|
||||
|
||||
@@ -142,4 +143,86 @@ describe('ObjectPatternPropertiesTransformer', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: destructuring default parameter with var shadowing', () => {
|
||||
describe('Variant #1: destructuring default should reference outer var, not inner var', () => {
|
||||
const code = `
|
||||
(function() {
|
||||
var x = 'outer';
|
||||
function f({ a = x } = {}) {
|
||||
var x = 'inner';
|
||||
return a;
|
||||
}
|
||||
return f();
|
||||
})();
|
||||
`;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(code, {
|
||||
...NO_ADDITIONAL_NODES_PRESET
|
||||
}).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should correctly resolve destructuring default to outer variable', () => {
|
||||
// Default parameter `a = x` should use outer 'x' value ('outer'),
|
||||
// NOT the inner var x = 'inner' which is in the function body scope
|
||||
assert.equal(evalLocal(code), 'outer');
|
||||
assert.equal(evalLocal(obfuscatedCode), evalLocal(code));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: nested destructuring default should reference outer var', () => {
|
||||
const code = `
|
||||
(function() {
|
||||
var x = 'outer';
|
||||
function f({ a: { b = x } } = { a: {} }) {
|
||||
var x = 'inner';
|
||||
return b;
|
||||
}
|
||||
return f();
|
||||
})();
|
||||
`;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(code, {
|
||||
...NO_ADDITIONAL_NODES_PRESET
|
||||
}).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should correctly resolve nested destructuring default to outer variable', () => {
|
||||
assert.equal(evalLocal(code), 'outer');
|
||||
assert.equal(evalLocal(obfuscatedCode), evalLocal(code));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: simple default param with var shadow', () => {
|
||||
const code = `
|
||||
(function() {
|
||||
var x = 'outer';
|
||||
function f(a = x) {
|
||||
var x = 'inner';
|
||||
return a;
|
||||
}
|
||||
return f();
|
||||
})();
|
||||
`;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(code, {
|
||||
...NO_ADDITIONAL_NODES_PRESET
|
||||
}).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should correctly resolve default param to outer variable', () => {
|
||||
assert.equal(evalLocal(code), 'outer');
|
||||
assert.equal(evalLocal(obfuscatedCode), evalLocal(code));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user