Skip to content

Commit

Permalink
fix: moved shortucts only initialized once (#12889) (#12938)
Browse files Browse the repository at this point in the history
Fix issuer with initializing shortcuts
for component delegation so the
shortcuts are not added with already
initialized actions.

Fixes #12307

Co-authored-by: caalador <mikael.grankvist@vaadin.com>
  • Loading branch information
vaadin-bot and caalador committed Feb 4, 2022
1 parent 091d431 commit daed8a6
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.vaadin.flow.function.SerializableSupplier;
import com.vaadin.flow.internal.ExecutionContext;
import com.vaadin.flow.internal.StateTree;
import com.vaadin.flow.internal.StringUtil;
import com.vaadin.flow.shared.Registration;

/**
Expand Down Expand Up @@ -62,6 +63,7 @@ public class ShortcutRegistration implements Registration, Serializable {
+ "}";//@formatter:on
private boolean allowDefaultBehavior = false;
private boolean allowEventPropagation = false;
static final String LISTEN_ON_INITIALIZED = "_initialized_listen_on_for_component";

private Set<Key> modifiers = new HashSet<>(2);
private Key primaryKey = null;
Expand Down Expand Up @@ -798,10 +800,37 @@ private void setupKeydownEventDelegateIfNeeded(Component listenOn) {
: "event.preventDefault();";
final String jsExpression = String.format(ELEMENT_LOCATOR_JS,
elementLocatorJs, filterText, preventDefault);

final String expressionHash = StringUtil.getHash(jsExpression);
final Set<String> expressions = getOrInitListenData(listenOn);
if (expressions.contains(expressionHash)) {
return;
}
expressions.add(expressionHash);
listenOn.getElement().executeJs(jsExpression);
}
}

/**
* Get the sent listenOn event data or initialize new listenOn data.
*
* @param listenOn
* component to listen events on
* @return set with already executed expressions.
*/
private Set<String> getOrInitListenData(Component listenOn) {
final Object componentData = ComponentUtil.getData(listenOn,
LISTEN_ON_INITIALIZED);
if (componentData != null) {
return (Set<String>) componentData;
}
final HashSet<String> expressionHash = new HashSet<>();
ComponentUtil.setData(listenOn, LISTEN_ON_INITIALIZED, expressionHash);
listenOn.addDetachListener(event -> ComponentUtil
.setData(event.getSource(), LISTEN_ON_INITIALIZED, null));
return expressionHash;
}

/**
* Wraps a {@link Key} instance. Makes it easier to compare the keys and
* store them by hash.
Expand Down
32 changes: 32 additions & 0 deletions flow-server/src/main/java/com/vaadin/flow/internal/StringUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
package com.vaadin.flow.internal;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.MessageDigestSpi;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
Expand Down Expand Up @@ -150,4 +154,32 @@ private static String generateReplacement(String str) {
}
return replacement;
}

/**
* Generate a hash for given content.
*
* @param content
* content to generate hash for
* @return hash String for given content. In case content is null or empty
* returns empty String.
*/
public static String getHash(String content) {
if (content == null || content.isEmpty()) {
return "";
}

return bytesToHex(MessageDigestUtil.sha256(content));
}

private static String bytesToHex(byte[] hash) {
StringBuilder result = new StringBuilder();
for (byte hashByte : hash) {
String hex = Integer.toHexString(0xff & hashByte);
if (hex.length() == 1) {
result.append('0');
}
result.append(hex);
}
return result.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.stream.Stream;

import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.internal.StringUtil;
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner;
import org.apache.commons.io.FileUtils;
Expand Down Expand Up @@ -501,34 +502,7 @@ static String generatePackageJsonHash(JsonObject packageJson) {
hashContent.append(sortedDevDependencies);
hashContent.append("}");
}
return getHash(hashContent.toString());
}

private static String getHash(String content) {
if (content.isEmpty()) {
return content;
}
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
return bytesToHex(
digest.digest(content.getBytes(StandardCharsets.UTF_8)));
} catch (NoSuchAlgorithmException e) {
// Unrecoverable runtime exception, that can not happen
throw new RuntimeException(
"Unable to find a provider for SHA-256 algorithm", e);
}
}

private static String bytesToHex(byte[] hash) {
StringBuilder result = new StringBuilder();
for (byte bit : hash) {
String hex = Integer.toHexString(0xff & bit);
if (hex.length() == 1) {
result.append('0');
}
result.append(hex);
}
return result.toString();
return StringUtil.getHash(hashContent.toString());
}

}

0 comments on commit daed8a6

Please sign in to comment.