mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
[Bug] Wrong Lexical Scope for let and const variables
This commit is contained in:
Vendored
+4
-4
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -21,6 +21,7 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
|
||||
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
|
||||
import { NodeGuards } from '../../node/NodeGuards';
|
||||
import { NodeLexicalScopeUtils } from '../../node/NodeLexicalScopeUtils';
|
||||
import { NodeBlockLexicalScopeUtils } from '../../node/NodeBlockLexicalScopeUtils';
|
||||
import { NodeMetadata } from '../../node/NodeMetadata';
|
||||
|
||||
/**
|
||||
@@ -93,7 +94,9 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
|
||||
* @returns {NodeGuards}
|
||||
*/
|
||||
public transformNode (variableDeclarationNode: ESTree.VariableDeclaration, parentNode: ESTree.Node): ESTree.Node {
|
||||
const lexicalScopeNode: TNodeWithLexicalScope | undefined = NodeLexicalScopeUtils.getLexicalScope(variableDeclarationNode);
|
||||
const lexicalScopeNode: TNodeWithLexicalScope | undefined = variableDeclarationNode.kind === 'var'
|
||||
? NodeLexicalScopeUtils.getLexicalScope(variableDeclarationNode)
|
||||
: NodeBlockLexicalScopeUtils.getLexicalScope(variableDeclarationNode);
|
||||
|
||||
if (!lexicalScopeNode) {
|
||||
return variableDeclarationNode;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { TNodeWithLexicalScope } from '../types/node/TNodeWithLexicalScope';
|
||||
|
||||
import { NodeGuards } from './NodeGuards';
|
||||
|
||||
export class NodeBlockLexicalScopeUtils {
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {TNodeWithLexicalScope}
|
||||
*/
|
||||
public static getLexicalScope (node: ESTree.Node): TNodeWithLexicalScope | undefined {
|
||||
return NodeBlockLexicalScopeUtils.getLexicalScopesRecursive(node, 1)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {TNodeWithLexicalScope[]}
|
||||
*/
|
||||
public static getLexicalScopes (node: ESTree.Node): TNodeWithLexicalScope[] {
|
||||
return NodeBlockLexicalScopeUtils.getLexicalScopesRecursive(node);
|
||||
}
|
||||
|
||||
/***
|
||||
* @param {Node} node
|
||||
* @param {number} maxSize
|
||||
* @param {TNodeWithLexicalScope[]} nodesWithLexicalScope
|
||||
* @param {number} depth
|
||||
* @returns {TNodeWithLexicalScope[]}
|
||||
*/
|
||||
private static getLexicalScopesRecursive (
|
||||
node: ESTree.Node,
|
||||
maxSize: number = Infinity,
|
||||
nodesWithLexicalScope: TNodeWithLexicalScope[] = [],
|
||||
depth: number = 0
|
||||
): TNodeWithLexicalScope[] {
|
||||
if (nodesWithLexicalScope.length >= maxSize) {
|
||||
return nodesWithLexicalScope;
|
||||
}
|
||||
|
||||
const parentNode: ESTree.Node | undefined = node.parentNode;
|
||||
|
||||
if (!parentNode) {
|
||||
throw new ReferenceError('`parentNode` property of given node is `undefined`');
|
||||
}
|
||||
|
||||
if (NodeGuards.isNodeWithBlockLexicalScope(node)) {
|
||||
nodesWithLexicalScope.push(node);
|
||||
}
|
||||
|
||||
if (node !== parentNode) {
|
||||
return NodeBlockLexicalScopeUtils.getLexicalScopesRecursive(parentNode, maxSize, nodesWithLexicalScope, ++depth);
|
||||
}
|
||||
|
||||
return nodesWithLexicalScope;
|
||||
}
|
||||
}
|
||||
@@ -223,6 +223,14 @@ export class NodeGuards {
|
||||
return NodeGuards.isProgramNode(node) || NodeGuards.isFunctionNode(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public static isNodeWithBlockLexicalScope (node: ESTree.Node): node is TNodeWithLexicalScope {
|
||||
return NodeGuards.isNodeWithLexicalScope(node) || NodeGuards.isBlockStatementNode(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @param {Node} parentNode
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
!function () {
|
||||
{
|
||||
let name;
|
||||
}
|
||||
{
|
||||
let {name} = {name: "foo"};
|
||||
console.log(name);
|
||||
}
|
||||
}();
|
||||
@@ -0,0 +1,31 @@
|
||||
import { assert } from 'chai';
|
||||
import { NO_ADDITIONAL_NODES_PRESET } from '../../../src/options/presets/NoCustomNodes';
|
||||
import { readFileAsString } from '../../helpers/readFileAsString';
|
||||
import { JavaScriptObfuscator } from '../../../src/JavaScriptObfuscatorFacade';
|
||||
|
||||
//
|
||||
// https://github.com/javascript-obfuscator/javascript-obfuscator/issues/424
|
||||
//
|
||||
describe('Issue #424', () => {
|
||||
|
||||
describe('Fixture code should nor break', () => {
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/issue424.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
stringArray: false
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
});
|
||||
|
||||
it('does not break on run', () => {
|
||||
assert.doesNotThrow(() => eval(obfuscatedCode));
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user