Skip to content

Commit

Permalink
Fixed #264
Browse files Browse the repository at this point in the history
  • Loading branch information
sanex3339 committed May 23, 2018
1 parent 833e832 commit 5867407
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 162 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Change Log
v0.17.0
---
* **Browser version**: Added browser version dist
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/264
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/260
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/252
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/247
Expand Down
4 changes: 2 additions & 2 deletions dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "0.17.0-dev.0",
"version": "0.17.0-dev.1",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down Expand Up @@ -54,17 +54,17 @@
"@types/mkdirp": "0.5.2",
"@types/mocha": "5.2.0",
"@types/multimatch": "2.1.2",
"@types/node": "10.1.1",
"@types/node": "10.1.2",
"@types/rimraf": "2.0.2",
"@types/sinon": "4.3.3",
"@types/string-template": "1.0.2",
"@types/webpack-env": "1.13.6",
"awesome-typescript-loader": "5.0.0",
"babel-loader": "8.0.0-beta.2",
"babel-loader": "8.0.0-beta.3",
"chai": "4.1.2",
"coveralls": "3.0.1",
"istanbul": "1.1.0-alpha.1",
"mocha": "5.1.1",
"mocha": "5.2.0",
"pjson": "1.0.9",
"pre-commit": "1.2.2",
"rimraf": "2.6.2",
Expand All @@ -78,7 +78,7 @@
"tslint-webpack-plugin": "1.2.2",
"typescript": "2.8.3",
"webpack": "4.8.3",
"webpack-cli": "2.1.3",
"webpack-cli": "2.1.4",
"webpack-node-externals": "1.7.2"
},
"repository": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import { NodeUtils } from '../../node/NodeUtils';
@injectable()
export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
/**
* @type {Map<VariableDeclarator, TNodeWithScope>}
* @type {Map<Node, TNodeWithScope>}
*/
private readonly cachedScopeNodesMap: Map <ESTree.VariableDeclarator, TNodeWithScope> = new Map();
private readonly cachedScopeNodesMap: Map <ESTree.Node, TNodeWithScope> = new Map();

/**
* @param {IRandomGenerator} randomGenerator
Expand All @@ -36,22 +36,23 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
}

/**
* @param {TNodeWithScope} scopeNode
* @param {ExpressionStatement[]} expressionStatements
* @param {Node} variableDeclarator
* Returns host statement of object expression node
*
* @param {NodeGuards} node
* @returns {Node}
*/
private static appendExpressionStatements (
scopeNode: TNodeWithScope,
expressionStatements: ESTree.ExpressionStatement[],
variableDeclarator: ESTree.Node
): void {
const variableDeclaration: ESTree.Node | undefined = variableDeclarator.parentNode;
public static getHostStatement (node: ESTree.Node): ESTree.Statement {
const parentNode: ESTree.Node | undefined = node.parentNode;

if (!variableDeclaration || !NodeGuards.isVariableDeclarationNode(variableDeclaration)) {
throw new Error('Cannot find variable declaration for variable declarator');
if (!parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}

NodeAppender.insertNodeAfter(scopeNode, expressionStatements, variableDeclaration);
if (!NodeGuards.isNodeHasScope(parentNode)) {
return ObjectExpressionKeysTransformer.getHostStatement(parentNode);
}

return <ESTree.Statement>node;
}

/**
Expand All @@ -63,6 +64,21 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
return properties.filter((property: ESTree.Property, index: number) => !removablePropertyIds.includes(index));
}

/**
* @param {TNodeWithScope} scopeNode
* @param {Node} hostNode
* @param {ExpressionStatement[]} expressionStatements
*/
private static appendExpressionStatements (
scopeNode: TNodeWithScope,
hostNode: ESTree.Node,
expressionStatements: ESTree.ExpressionStatement[]
): void {
const hostNodeScope: ESTree.Node = ObjectExpressionKeysTransformer.getHostStatement(hostNode);

NodeAppender.insertNodeAfter(scopeNode, expressionStatements, hostNodeScope);
}

/**
* @param {Property} propertyNode
* @returns {string | null}
Expand All @@ -85,13 +101,13 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {

/**
* @param {Expression | Pattern} propertyValueNode
* @returns {boolean}
* @returns {propertyValueNode is Expression}
*/
private static isValidPropertyValueNode (propertyValueNode: ESTree.Expression | ESTree.Pattern): propertyValueNode is ESTree.Expression {
private static isValidExpressionNode (propertyValueNode: ESTree.Expression | ESTree.Pattern): propertyValueNode is ESTree.Expression {
return !NodeGuards.isObjectPatternNode(propertyValueNode)
&& !NodeGuards.isArrayPatternNode(propertyValueNode)
&& !NodeGuards.isAssignmentPatternNode(propertyValueNode)
&& !NodeGuards.isRestElementNode(propertyValueNode);
&& !NodeGuards.isArrayPatternNode(propertyValueNode)
&& !NodeGuards.isAssignmentPatternNode(propertyValueNode)
&& !NodeGuards.isRestElementNode(propertyValueNode);
}

/**
Expand All @@ -107,7 +123,6 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
this.options.transformObjectKeys
&& parentNode
&& NodeGuards.isObjectExpressionNode(node)
&& NodeGuards.isVariableDeclaratorNode(parentNode)
) {
return this.transformNode(node, parentNode);
}
Expand All @@ -132,40 +147,90 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
* object['bar'] = 2;
*
* @param {MemberExpression} objectExpressionNode
* @param {NodeGuards} variableDeclarator
* @param {Node} parentNode
* @returns {NodeGuards}
*/
public transformNode (objectExpressionNode: ESTree.ObjectExpression, variableDeclarator: ESTree.VariableDeclarator): ESTree.Node {
public transformNode (objectExpressionNode: ESTree.ObjectExpression, parentNode: ESTree.Node): ESTree.Node {
if (NodeGuards.isVariableDeclaratorNode(parentNode)) {
return this.transformVariableDeclaratorHostObjectExpression(objectExpressionNode, parentNode);
}

if (NodeGuards.isAssignmentExpressionNode(parentNode)) {
return this.transformAssignmentExpressionHostObjectExpression(objectExpressionNode, parentNode);
}

return objectExpressionNode;
}

/**
* @param {ObjectExpression} objectExpressionNode
* @param {VariableDeclarator} variableDeclaratorNode
* @returns {Node}
*/
private transformVariableDeclaratorHostObjectExpression(
objectExpressionNode: ESTree.ObjectExpression,
variableDeclaratorNode: ESTree.VariableDeclarator
): ESTree.Node {
// should pass only Expression nodes as MemberExpression.object value
if (!NodeGuards.isIdentifierNode(variableDeclarator.id)) {
if (!NodeGuards.isIdentifierNode(variableDeclaratorNode.id)) {
return objectExpressionNode;
}

const scopeNode: TNodeWithScope | null = NodeUtils.getScopeOfNode(variableDeclaratorNode);

if (!scopeNode || !NodeGuards.isNodeHasScope(scopeNode)) {
return objectExpressionNode;
}

this.cachedScopeNodesMap.set(variableDeclaratorNode, scopeNode);

return this.transformObjectExpressionNode(
objectExpressionNode,
variableDeclaratorNode.id,
variableDeclaratorNode
);
}

/**
* @param {ObjectExpression} objectExpressionNode
* @param {AssignmentExpression} assignmentExpressionNode
* @returns {Node}
*/
private transformAssignmentExpressionHostObjectExpression(
objectExpressionNode: ESTree.ObjectExpression,
assignmentExpressionNode: ESTree.AssignmentExpression
): ESTree.Node {
const leftNode: ESTree.MemberExpression | ESTree.Pattern = assignmentExpressionNode.left;

if (!ObjectExpressionKeysTransformer.isValidExpressionNode(leftNode)) {
return objectExpressionNode;
}

const scopeNode: TNodeWithScope | null = NodeUtils.getScopeOfNode(variableDeclarator);
const scopeNode: TNodeWithScope | null = NodeUtils.getScopeOfNode(assignmentExpressionNode);

if (!scopeNode || !NodeGuards.isNodeHasScope(scopeNode)) {
return objectExpressionNode;
}

this.cachedScopeNodesMap.set(variableDeclarator, scopeNode);
this.cachedScopeNodesMap.set(assignmentExpressionNode, scopeNode);

return this.transformObjectExpressionNode(
objectExpressionNode,
variableDeclarator.id,
variableDeclarator
leftNode,
assignmentExpressionNode
);
}

/**
* @param {Property[]} properties
* @param {Expression} memberExpressionObject
* @param {VariableDeclarator} variableDeclarator
* @param {Node} hostNode
* @returns {[ExpressionStatement[] , number[]]}
*/
private extractPropertiesToExpressionStatements (
properties: ESTree.Property[],
memberExpressionObject: ESTree.Expression,
variableDeclarator: ESTree.VariableDeclarator
hostNode: ESTree.Node
): [ESTree.ExpressionStatement[], number[]] {
const propertiesLength: number = properties.length;
const expressionStatements: ESTree.ExpressionStatement[] = [];
Expand All @@ -176,7 +241,7 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
const propertyValue: ESTree.Expression | ESTree.Pattern = property.value;

// invalid property nodes
if (!ObjectExpressionKeysTransformer.isValidPropertyValueNode(propertyValue)) {
if (!ObjectExpressionKeysTransformer.isValidExpressionNode(propertyValue)) {
continue;
}

Expand Down Expand Up @@ -207,7 +272,7 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
* Stage 3: recursively processing nested object expressions
*/
if (NodeGuards.isObjectExpressionNode(property.value)) {
this.transformObjectExpressionNode(property.value, memberExpressionNode, variableDeclarator);
this.transformObjectExpressionNode(property.value, memberExpressionNode, hostNode);
}

/**
Expand All @@ -223,33 +288,33 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
/**
* @param {ObjectExpression} objectExpressionNode
* @param {Expression} memberExpressionObjectNode
* @param {VariableDeclarator} variableDeclarator
* @param {Node} hostNode
* @returns {Node}
*/
private transformObjectExpressionNode (
objectExpressionNode: ESTree.ObjectExpression,
memberExpressionObjectNode: ESTree.Expression,
variableDeclarator: ESTree.VariableDeclarator
hostNode: ESTree.Node
): ESTree.Node {
const properties: ESTree.Property[] = objectExpressionNode.properties;

if (!properties.length) {
return objectExpressionNode;
}

const scopeNode: TNodeWithScope | undefined = this.cachedScopeNodesMap.get(variableDeclarator);
const scopeNode: TNodeWithScope | undefined = this.cachedScopeNodesMap.get(hostNode);

if (!scopeNode) {
return objectExpressionNode;
}

const [expressionStatements, removablePropertyIds]: [ESTree.ExpressionStatement[], number[]] = this
.extractPropertiesToExpressionStatements(properties, memberExpressionObjectNode, variableDeclarator);
.extractPropertiesToExpressionStatements(properties, memberExpressionObjectNode, hostNode);

objectExpressionNode.properties = ObjectExpressionKeysTransformer
.filterObjectExpressionProperties(properties, removablePropertyIds);
ObjectExpressionKeysTransformer
.appendExpressionStatements(scopeNode, expressionStatements, variableDeclarator);
.appendExpressionStatements(scopeNode, objectExpressionNode, expressionStatements);

return objectExpressionNode;
}
Expand Down
8 changes: 8 additions & 0 deletions src/node/NodeGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ export class NodeGuards {
return node.type === NodeType.ArrowFunctionExpression;
}

/**
* @param {Node} node
* @returns {boolean}
*/
public static isAssignmentExpressionNode (node: ESTree.Node): node is ESTree.AssignmentExpression {
return node.type === NodeType.AssignmentExpression;
}

/**
* @param {Node} node
* @returns {boolean}
Expand Down

0 comments on commit 5867407

Please sign in to comment.