Skip to content

fix: invalid Android invalidation of hybrid data #7197

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.swmansion.worklets.WorkletsModule;
import java.lang.ref.WeakReference;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* @noinspection JavaJniMissingFunction
Expand All @@ -47,6 +48,12 @@ public class NativeProxy {
private final int ANIMATIONS_DRAG_FACTOR = 10;
protected String cppVersion = null;

/**
* Invalidating concurrently could be fatal. It shouldn't happen in a normal flow, but it doesn't
* cost us much to add synchronization for extra safety.
*/
private final AtomicBoolean mInvalidated = new AtomicBoolean(false);

@DoNotStrip
@SuppressWarnings("unused")
private final HybridData mHybridData;
Expand Down Expand Up @@ -105,8 +112,13 @@ protected HybridData getHybridData() {
return mHybridData;
}

public void invalidate() {
invalidateCpp();
protected void invalidate() {
if (mInvalidated.getAndSet(true)) {
return;
}
if (mHybridData != null && mHybridData.isValid()) {
invalidateCpp();
}
}

private void toggleSlowAnimations() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.swmansion.worklets.runloop.AnimationFrameCallback;
import com.swmansion.worklets.runloop.AnimationFrameQueue;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

@SuppressWarnings("JavaJniMissingFunction")
@ReactModule(name = WorkletsModule.NAME)
Expand All @@ -36,6 +37,12 @@ protected HybridData getHybridData() {
private final AnimationFrameQueue mAnimationFrameQueue;
private boolean mSlowAnimationsEnabled;

/**
* Invalidating concurrently could be fatal. It shouldn't happen in a normal flow, but it doesn't
* cost us much to add synchronization for extra safety.
*/
private final AtomicBoolean mInvalidated = new AtomicBoolean(false);

@OptIn(markerClass = FrameworkAPI.class)
private native HybridData initHybrid(
long jsContext,
Expand Down Expand Up @@ -81,11 +88,15 @@ public void toggleSlowAnimations() {
}

public void invalidate() {
// We have to destroy extra runtimes when invalidate is called. If we clean
// it up later instead there's a chance the runtime will retain references
// to invalidated memory and will crash on its destruction.
invalidateCpp();

if (mInvalidated.getAndSet(true)) {
return;
}
if (mHybridData != null && mHybridData.isValid()) {
// We have to destroy extra runtimes when invalidate is called. If we clean
// it up later instead there's a chance the runtime will retain references
// to invalidated memory and will crash on its destruction.
invalidateCpp();
}
mAndroidUIScheduler.deactivate();
}

Expand Down
Loading