From 4ffe74296d1467311b97513c9ea3752bdb1db4b9 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 21 Dec 2018 14:28:30 +0300 Subject: [PATCH] Limit max line size of generated JS code --- .../java/lang/ClassLoaderNativeGenerator.java | 4 +- .../javascript/rendering/Renderer.java | 2 +- .../javascript/rendering/RenderingUtil.java | 55 +++++++++++++++++++ .../platform/plugin/BuildTimeResourceMap.java | 7 ++- .../platform/plugin/ResourceWriterHelper.java | 37 ++----------- 5 files changed, 66 insertions(+), 39 deletions(-) diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/ClassLoaderNativeGenerator.java b/classlib/src/main/java/org/teavm/classlib/java/lang/ClassLoaderNativeGenerator.java index c43645492..e51f3c868 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/ClassLoaderNativeGenerator.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/ClassLoaderNativeGenerator.java @@ -74,9 +74,9 @@ public class ClassLoaderNativeGenerator implements Injector { for (int i = 0; i < dataBytes.length; ++i) { dataChars[i] = (char) dataBytes[i]; } - writer.append("\"").append(RenderingUtil.escapeString(resource)).append("\""); + RenderingUtil.writeString(writer, resource); writer.ws().append(':').ws(); - writer.append("\"").append(new String(dataChars)).append("\""); + RenderingUtil.writeString(writer, new String(dataChars)); } } diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java b/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java index cd72cf654..9b771522b 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java @@ -183,7 +183,7 @@ public class Renderer implements RenderingManager { if (i > 0) { writer.append(',').ws(); } - writer.append('"').append(RenderingUtil.escapeString(context.getStringPool().get(i))).append('"'); + RenderingUtil.writeString(writer, context.getStringPool().get(i)); } writer.append("]);").newLine(); stringPoolSize = writer.getOffset() - start; diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/RenderingUtil.java b/core/src/main/java/org/teavm/backend/javascript/rendering/RenderingUtil.java index c9bdc2a16..6451a781f 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/RenderingUtil.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/RenderingUtil.java @@ -15,12 +15,14 @@ */ package org.teavm.backend.javascript.rendering; +import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.teavm.ast.ConstantExpr; import org.teavm.ast.Expr; +import org.teavm.backend.javascript.codegen.SourceWriter; public final class RenderingUtil { public static final Set KEYWORDS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("break", "case", @@ -43,6 +45,59 @@ public final class RenderingUtil { return sb.toString(); } + public static void writeString(SourceWriter writer, String s) throws IOException { + if (s.isEmpty()) { + writer.append("\"\""); + return; + } + for (int i = 0; i < s.length(); i += 512) { + int next = Math.min(i + 512, s.length()); + if (i > 0) { + writer.newLine().append("+").ws(); + } + writer.append('"'); + for (int j = i; j < next; ++j) { + char c = s.charAt(j); + switch (c) { + case '\r': + writer.append("\\r"); + break; + case '\n': + writer.append("\\n"); + break; + case '\t': + writer.append("\\t"); + break; + case '\'': + writer.append("\\'"); + break; + case '\"': + writer.append("\\\""); + break; + case '\\': + writer.append("\\\\"); + break; + default: + if (c < ' ') { + writer.append("\\u00").append(Character.forDigit(c / 16, 16)) + .append(Character.forDigit(c % 16, 16)); + } else if (Character.isLowSurrogate(c) || Character.isHighSurrogate(c) + || !Character.isDefined(c)) { + writer.append("\\u") + .append(Character.forDigit(c / 0x1000, 0x10)) + .append(Character.forDigit((c / 0x100) % 0x10, 0x10)) + .append(Character.forDigit((c / 0x10) % 0x10, 0x10)) + .append(Character.forDigit(c % 0x10, 0x10)); + } else { + writer.append(c); + } + break; + } + } + writer.append('"'); + } + } + public static String escapeString(String str) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < str.length(); ++i) { diff --git a/platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceMap.java b/platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceMap.java index 8b30c7e42..91317c92f 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceMap.java +++ b/platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceMap.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.teavm.backend.javascript.codegen.SourceWriter; +import org.teavm.backend.javascript.rendering.RenderingUtil; import org.teavm.platform.metadata.Resource; import org.teavm.platform.metadata.ResourceMap; @@ -49,8 +50,8 @@ class BuildTimeResourceMap implements ResourceMap, Resour writer.append(",").ws(); } first = false; - ResourceWriterHelper.writeString(writer, entry.getKey()); - writer.ws().append(':').ws(); + RenderingUtil.writeString(writer, entry.getKey()); + writer.append(':').ws(); ResourceWriterHelper.write(writer, entry.getValue()); } writer.append('}').tokenBoundary(); @@ -58,6 +59,6 @@ class BuildTimeResourceMap implements ResourceMap, Resour @Override public String[] keys() { - return data.keySet().toArray(new String[data.size()]); + return data.keySet().toArray(new String[0]); } } diff --git a/platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java b/platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java index 71f95dc3a..220407a89 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java +++ b/platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java @@ -17,6 +17,7 @@ package org.teavm.platform.plugin; import java.io.IOException; import org.teavm.backend.javascript.codegen.SourceWriter; +import org.teavm.backend.javascript.rendering.RenderingUtil; final class ResourceWriterHelper { private ResourceWriterHelper() { @@ -33,7 +34,7 @@ final class ResourceWriterHelper { } else if (resource instanceof Boolean) { writer.append(resource == Boolean.TRUE ? "true" : "false"); } else if (resource instanceof String) { - writeString(writer, (String) resource); + RenderingUtil.writeString(writer, (String) resource); } else { throw new RuntimeException("Error compiling resources. Value of illegal type found: " + resource.getClass()); @@ -43,12 +44,12 @@ final class ResourceWriterHelper { public static void writeIdentifier(SourceWriter writer, String id) throws IOException { if (id.isEmpty() || !isIdentifierStart(id.charAt(0))) { - writeString(writer, id); + RenderingUtil.writeString(writer, id); return; } for (int i = 1; i < id.length(); ++i) { if (isIdentifierPart(id.charAt(i))) { - writeString(writer, id); + RenderingUtil.writeString(writer, id); return; } } @@ -68,34 +69,4 @@ final class ResourceWriterHelper { } return c >= '0' && c <= '9'; } - - public static void writeString(SourceWriter writer, String s) throws IOException { - writer.append('"'); - for (int i = 0; i < s.length(); ++i) { - char c = s.charAt(i); - switch (c) { - case '\0': - writer.append("\\0"); - break; - case '\n': - writer.append("\\n"); - break; - case '\r': - writer.append("\\r"); - break; - case '\t': - writer.append("\\t"); - break; - default: - if (c < 32) { - writer.append("\\u00").append(Character.forDigit(c / 16, 16)) - .append(Character.forDigit(c % 16, 16)); - } else { - writer.append(c); - } - break; - } - } - writer.append('"'); - } }