mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
js: make names of variables in minified mode never interfering with JS keywords
This commit is contained in:
parent
1989fb70a4
commit
900f95c1ed
|
@ -21,11 +21,9 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
|
||||||
import org.teavm.ast.ArrayFromDataExpr;
|
import org.teavm.ast.ArrayFromDataExpr;
|
||||||
import org.teavm.ast.AssignmentStatement;
|
import org.teavm.ast.AssignmentStatement;
|
||||||
import org.teavm.ast.BinaryExpr;
|
import org.teavm.ast.BinaryExpr;
|
||||||
|
@ -66,7 +64,6 @@ import org.teavm.ast.TryCatchStatement;
|
||||||
import org.teavm.ast.UnaryExpr;
|
import org.teavm.ast.UnaryExpr;
|
||||||
import org.teavm.ast.UnwrapArrayExpr;
|
import org.teavm.ast.UnwrapArrayExpr;
|
||||||
import org.teavm.ast.VariableExpr;
|
import org.teavm.ast.VariableExpr;
|
||||||
import org.teavm.ast.VariableNode;
|
|
||||||
import org.teavm.ast.WhileStatement;
|
import org.teavm.ast.WhileStatement;
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
|
@ -98,14 +95,12 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
private DeferredCallSite prevCallSite;
|
private DeferredCallSite prevCallSite;
|
||||||
private boolean end;
|
private boolean end;
|
||||||
private final Map<String, String> blockIdMap = new HashMap<>();
|
private final Map<String, String> blockIdMap = new HashMap<>();
|
||||||
private final List<String> cachedVariableNames = new ArrayList<>();
|
|
||||||
private final Set<String> usedVariableNames = new HashSet<>();
|
|
||||||
private MethodNode currentMethod;
|
|
||||||
private int currentPart;
|
private int currentPart;
|
||||||
private List<String> blockIds = new ArrayList<>();
|
private List<String> blockIds = new ArrayList<>();
|
||||||
private IntIndexedContainer blockIndexMap = new IntArrayList();
|
private IntIndexedContainer blockIndexMap = new IntArrayList();
|
||||||
private boolean longLibraryUsed;
|
private boolean longLibraryUsed;
|
||||||
private static final MethodDescriptor CLINIT_METHOD = new MethodDescriptor("<clinit>", ValueType.VOID);
|
private static final MethodDescriptor CLINIT_METHOD = new MethodDescriptor("<clinit>", ValueType.VOID);
|
||||||
|
private VariableNameGenerator variableNameGenerator;
|
||||||
|
|
||||||
public StatementRenderer(RenderingContext context, SourceWriter writer) {
|
public StatementRenderer(RenderingContext context, SourceWriter writer) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
@ -114,11 +109,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
this.minifying = context.isMinifying();
|
this.minifying = context.isMinifying();
|
||||||
this.naming = context.getNaming();
|
this.naming = context.getNaming();
|
||||||
this.debugEmitter = context.getDebugEmitter();
|
this.debugEmitter = context.getDebugEmitter();
|
||||||
if (!minifying) {
|
variableNameGenerator = new VariableNameGenerator(minifying);
|
||||||
usedVariableNames.add("$tmp");
|
|
||||||
usedVariableNames.add("$ptr");
|
|
||||||
usedVariableNames.add("$thread");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLongLibraryUsed() {
|
public boolean isLongLibraryUsed() {
|
||||||
|
@ -134,7 +125,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentMethod(MethodNode currentMethod) {
|
public void setCurrentMethod(MethodNode currentMethod) {
|
||||||
this.currentMethod = currentMethod;
|
variableNameGenerator.setCurrentMethod(currentMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentPart(int currentPart) {
|
public void setCurrentPart(int currentPart) {
|
||||||
|
@ -492,38 +483,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String variableName(int index) {
|
public String variableName(int index) {
|
||||||
while (index >= cachedVariableNames.size()) {
|
return variableNameGenerator.variableName(index);
|
||||||
cachedVariableNames.add(null);
|
|
||||||
}
|
|
||||||
String name = cachedVariableNames.get(index);
|
|
||||||
if (name == null) {
|
|
||||||
name = generateVariableName(index);
|
|
||||||
cachedVariableNames.set(index, name);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String generateVariableName(int index) {
|
|
||||||
if (!minifying) {
|
|
||||||
VariableNode variable = currentMethod != null && index < currentMethod.getVariables().size()
|
|
||||||
? currentMethod.getVariables().get(index)
|
|
||||||
: null;
|
|
||||||
if (variable != null && variable.getName() != null) {
|
|
||||||
String result = "$" + RenderingUtil.escapeName(variable.getName());
|
|
||||||
if (RenderingUtil.KEYWORDS.contains(result) || !usedVariableNames.add(result)) {
|
|
||||||
String base = result;
|
|
||||||
int suffix = 0;
|
|
||||||
do {
|
|
||||||
result = base + "_" + suffix++;
|
|
||||||
} while (!usedVariableNames.add(result));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return "var$" + index;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return RenderingUtil.indexToId(index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitBinary(BinaryExpr expr, String op, boolean guarded) {
|
private void visitBinary(BinaryExpr expr, String op, boolean guarded) {
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.javascript.rendering;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.teavm.ast.MethodNode;
|
||||||
|
|
||||||
|
public class VariableNameGenerator {
|
||||||
|
private boolean minifying;
|
||||||
|
private final List<String> cachedVariableNames = new ArrayList<>();
|
||||||
|
private int cachedVariableNameLastIndex;
|
||||||
|
private MethodNode currentMethod;
|
||||||
|
private Set<String> usedVariableNames = new HashSet<>();
|
||||||
|
|
||||||
|
public VariableNameGenerator(boolean minifying) {
|
||||||
|
this.minifying = minifying;
|
||||||
|
if (!minifying) {
|
||||||
|
usedVariableNames.add("$tmp");
|
||||||
|
usedVariableNames.add("$ptr");
|
||||||
|
usedVariableNames.add("$thread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentMethod(MethodNode currentMethod) {
|
||||||
|
this.currentMethod = currentMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String variableName(int index) {
|
||||||
|
if (!minifying) {
|
||||||
|
while (index >= cachedVariableNames.size()) {
|
||||||
|
cachedVariableNames.add(null);
|
||||||
|
}
|
||||||
|
String name = cachedVariableNames.get(index);
|
||||||
|
if (name == null) {
|
||||||
|
name = generateVariableName(index);
|
||||||
|
cachedVariableNames.set(index, name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
} else {
|
||||||
|
while (index >= cachedVariableNames.size()) {
|
||||||
|
String name;
|
||||||
|
do {
|
||||||
|
name = RenderingUtil.indexToId(cachedVariableNameLastIndex++);
|
||||||
|
} while (RenderingUtil.KEYWORDS.contains(name));
|
||||||
|
cachedVariableNames.add(name);
|
||||||
|
}
|
||||||
|
return cachedVariableNames.get(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateVariableName(int index) {
|
||||||
|
var variable = currentMethod != null && index < currentMethod.getVariables().size()
|
||||||
|
? currentMethod.getVariables().get(index)
|
||||||
|
: null;
|
||||||
|
if (variable != null && variable.getName() != null) {
|
||||||
|
String result = "$" + RenderingUtil.escapeName(variable.getName());
|
||||||
|
if (RenderingUtil.KEYWORDS.contains(result) || !usedVariableNames.add(result)) {
|
||||||
|
String base = result;
|
||||||
|
int suffix = 0;
|
||||||
|
do {
|
||||||
|
result = base + "_" + suffix++;
|
||||||
|
} while (!usedVariableNames.add(result));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return "var$" + index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.javascript.rendering;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class VariableRenderingTest {
|
||||||
|
@Test
|
||||||
|
public void shortenedNames() {
|
||||||
|
var generator = new VariableNameGenerator(true);
|
||||||
|
var usedNames = new HashSet<String>();
|
||||||
|
for (var i = 0; i < 10000; ++i) {
|
||||||
|
var name = generator.variableName(i);
|
||||||
|
assertTrue(usedNames.add(name));
|
||||||
|
assertFalse(RenderingUtil.KEYWORDS.contains(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user