Skip to content
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

[iOS] Clicking just before a Special Character in a TextField causes a Crash #4388

Closed
mofeejegi opened this issue Feb 28, 2024 · 3 comments · Fixed by JetBrains/compose-multiplatform-core#1151
Assignees
Labels
bug Something isn't working crash input Touch, mouse, keyboard input related ios p:high High priority regression reproduced text

Comments

@mofeejegi
Copy link

Describe the bug
On iOS, whenever I'm typing some characters into a TextField, in my case an email address, I noticed that clicking just before any special Character (e.g: the '@' or '.') in the text (email) causes a crash.

Affected platforms
Select one of the platforms below:

  • iOS

Versions

  • Kotlin version: 1.9.22
  • Compose Multiplatform version(s): 1.6.0-rc02 - 1.6.0
  • OS version: iOS 17.2
  • OS architecture: arm64

To Reproduce
Steps and/or the code snippet to reproduce the behavior:

  1. Create a TextField and make it functional (value, onValueChanged, etc)
  2. Type any number of characters, type a special character (e.g: '@'), type some more characters after
  3. User your pointer or finger to click the index before the special char.
  4. See crash

Expected behavior
The cursor should appear in the clicked position.

Screen Recording

Screen.Recording.2024-02-28.at.18.26.10.mov

Additional context
The error stack trace is a bit lengthy, but it starts like this:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	       0x102c48a4c __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x102ce31d0 pthread_kill + 256
2   libsystem_c.dylib             	       0x1801605cc abort + 104
3   Font Test                     	       0x100becd94 konan::abort() + 12
4   Font Test                     	       0x100bfca94 (anonymous namespace)::terminateWithUnhandledException(ObjHeader*)::$_1::operator()() const + 16
5   Font Test                     	       0x100bfc8b0 void (anonymous namespace)::$_0::operator()<(anonymous namespace)::terminateWithUnhandledException(ObjHeader*)::$_1>((anonymous namespace)::terminateWithUnhandledException(ObjHeader*)::$_1) + 80
6   Font Test                     	       0x100bfc4ec (anonymous namespace)::terminateWithUnhandledException(ObjHeader*) + 12
7   Font Test                     	       0x100bfc4a8 (anonymous namespace)::processUnhandledException(ObjHeader*) + 64
8   Font Test                     	       0x100329760 kfun:kotlinx.coroutines.internal#propagateExceptionFinalResort(kotlin.Throwable){} + 120 (CoroutineExceptionHandlerImpl.kt:27)
9   Font Test                     	       0x1002fbb1c kfun:kotlinx.coroutines.internal#handleUncaughtCoroutineException(kotlin.coroutines.CoroutineContext;kotlin.Throwable){} + 760 (CoroutineExceptionHandlerImpl.common.kt:52)
10  Font Test                     	       0x1002a0578 kfun:kotlinx.coroutines#handleCoroutineException(kotlin.coroutines.CoroutineContext;kotlin.Throwable){} + 516 (CoroutineExceptionHandler.kt:32)
11  Font Test                     	       0x100293c30 kfun:kotlinx.coroutines.StandaloneCoroutine.handleJobException#internal + 168 (Builders.common.kt:194)
12  Font Test                     	       0x1003308ec kfun:kotlinx.coroutines.JobSupport#handleJobException(kotlin.Throwable){}kotlin.Boolean-trampoline + 60 (JobSupport.kt:1031)
13  Font Test                     	       0x1002aab20 kfun:kotlinx.coroutines.JobSupport.finalizeFinishingState#internal + 1192 (JobSupport.kt:231)
14  Font Test                     	       0x1002b360c kfun:kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath#internal + 2136 (JobSupport.kt:910)
15  Font Test                     	       0x1002b2d7c kfun:kotlinx.coroutines.JobSupport.tryMakeCompleting#internal + 756 (JobSupport.kt:867)
@mofeejegi mofeejegi added bug Something isn't working submitted labels Feb 28, 2024
@mofeejegi mofeejegi changed the title [IOS] Clicking just before a Special Character in a TextField causes a Crash [iOS] Clicking just before a Special Character in a TextField causes a Crash Feb 28, 2024
@MatkovIvan MatkovIvan added input Touch, mouse, keyboard input related text crash ios regression and removed submitted labels Feb 29, 2024
@elijah-semyonov
Copy link
Contributor

Hi, thanks for the report, I'll have a look

elijah-semyonov added a commit to JetBrains/compose-multiplatform-core that referenced this issue Feb 29, 2024
## Proposed Changes

Fix OutOfBounds logical error leading to crash. Refactor testing of
caret placement to be more apparent.

## Testing

Test:
CupertinoTextFieldDelegateTest.determineCursorDesiredOffset_tap_before_punctuation

## Issues Fixed

Fixes: JetBrains/compose-multiplatform#4388

## Note
This PR fixes the crash, the behavior is still incorrect. Consult with
code owner @mazunin-v-jb.
igordmn pushed a commit to JetBrains/compose-multiplatform-core that referenced this issue Mar 4, 2024
## Proposed Changes

Fix OutOfBounds logical error leading to crash. Refactor testing of
caret placement to be more apparent.

## Testing

Test:
CupertinoTextFieldDelegateTest.determineCursorDesiredOffset_tap_before_punctuation

## Issues Fixed

Fixes: JetBrains/compose-multiplatform#4388

## Note
This PR fixes the crash, the behavior is still incorrect. Consult with
code owner @mazunin-v-jb.
@okushnikov
Copy link
Collaborator

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

@babew
Copy link

babew commented Nov 22, 2024

Hello,

I have pretty same stack trace but the crash is from AppStore and I can't reproduce it. I saw that it isn't like the crash in this ticket but I will post my stack trace here.

#0	0x107f6dd18 in <inlined-out:<anonymous>> ()
#1	0x107f6dd18 in kfun:kotlin#apply__at__0:0(kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}0:0 ()
#2	0x107f6dd18 in kfun:kotlinx.coroutines#handlerException(kotlin.Throwable;kotlin.Throwable){}kotlin.Throwable ()
#3	0x107f6dbfc in kfun:kotlinx.coroutines#handleCoroutineException(kotlin.coroutines.CoroutineContext;kotlin.Throwable){} ()
#4	0x107f64ecc in kfun:kotlinx.coroutines.StandaloneCoroutine.handleJobException#internal ()
#5	0x107f748fc in kfun:kotlinx.coroutines.JobSupport#handleJobException(kotlin.Throwable){}kotlin.Boolean-trampoline ()
#6	0x107f748fc in kfun:kotlinx.coroutines.JobSupport.finalizeFinishingState#internal ()
#7	0x107f792fc in kfun:kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath#internal ()
#8	0x107f792fc in kfun:kotlinx.coroutines.JobSupport.tryMakeCompleting#internal ()
#9	0x107f78b08 in <inlined-out:<anonymous>> ()
#10	0x107f78b08 in <inlined-out:loopOnState> ()
#11	0x107f78b08 in kfun:kotlinx.coroutines.JobSupport#makeCompletingOnce(kotlin.Any?){}kotlin.Any? ()
#12	0x107f63588 in kfun:kotlinx.coroutines.AbstractCoroutine#resumeWith(kotlin.Result<1:0>){} ()
#13	0x107a7f378 in <inlined-out:<anonymous>> ()
#14	0x107a7f378 in kfun:kotlin#with(0:0;kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}0:1 ()
#15	0x107a7f378 in kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} ()
#16	0x107fac13c in kfun:kotlinx.coroutines.internal.ScopeCoroutine#afterResume(kotlin.Any?){} ()
#17	0x107f635e4 in kfun:kotlinx.coroutines.AbstractCoroutine#afterResume(kotlin.Any?){}-trampoline ()
#18	0x107f635e4 in kfun:kotlinx.coroutines.AbstractCoroutine#resumeWith(kotlin.Result<1:0>){} ()
#19	0x107a7f378 in <inlined-out:<anonymous>> ()
#20	0x107a7f378 in kfun:kotlin#with(0:0;kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}0:1 ()
#21	0x107a7f378 in kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} ()
#22	0x107fa82f4 in kfun:kotlin.coroutines#resumeWithException__at__kotlin.coroutines.Continuation<0:0>(kotlin.Throwable){0§<kotlin.Any?>} ()
#23	0x107fa82f4 in <inlined-out:<anonymous>> ()
#24	0x107fa82f4 in kfun:kotlinx.coroutines#withContinuationContext(kotlin.coroutines.Continuation<*>;kotlin.Any?;kotlin.Function0<0:0>){0§<kotlin.Any?>}0:0 ()
#25	0x107fa82f4 in kfun:kotlinx.coroutines.DispatchedTask#run(){} ()
#26	0x107fa9758 in kfun:kotlinx.coroutines.internal.LimitedDispatcher.Worker.run#internal ()
#27	0x107fbc0f8 in kfun:kotlinx.coroutines.MultiWorkerDispatcher.$workerRunLoop$lambda$2COROUTINE$0.invokeSuspend#internal ()
#28	0x107a7f28c in kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#invokeSuspend(kotlin.Result<kotlin.Any?>){}kotlin.Any?-trampoline ()
#29	0x107a7f28c in <inlined-out:<anonymous>> ()
#30	0x107a7f28c in kfun:kotlin#with(0:0;kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}0:1 ()
#31	0x107a7f28c in kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} ()
#32	0x107fa8368 in kfun:kotlin.coroutines#resume__at__kotlin.coroutines.Continuation<0:0>(0:0){0§<kotlin.Any?>} ()
#33	0x107fa8368 in <inlined-out:<anonymous>> ()
#34	0x107fa8368 in kfun:kotlinx.coroutines#withContinuationContext(kotlin.coroutines.Continuation<*>;kotlin.Any?;kotlin.Function0<0:0>){0§<kotlin.Any?>}0:0 ()
#35	0x107fa8368 in kfun:kotlinx.coroutines.DispatchedTask#run(){} ()
#36	0x107f716f4 in <inlined-out:<anonymous>> ()
#37	0x107f716f4 in <inlined-out:<anonymous>> ()
#38	0x107f716f4 in kfun:kotlinx.cinterop#autoreleasepool(kotlin.Function0<0:0>){0§<kotlin.Any?>}0:0 ()
#39	0x107f716f4 in kfun:kotlinx.coroutines#platformAutoreleasePool(kotlin.Function0<kotlin.Unit>){} ()
#40	0x107f716f4 in kfun:kotlinx.coroutines.EventLoopImplBase#processNextEvent(){}kotlin.Long ()
#41	0x107fb6ee8 in kfun:kotlinx.coroutines.EventLoop#processNextEvent(){}kotlin.Long-trampoline ()
#42	0x107fb6ee8 in kfun:kotlinx.coroutines.BlockingCoroutine.joinBlocking#internal ()
#43	0x107fb6ee8 in kfun:kotlinx.coroutines#runBlocking(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,0:0>){0§<kotlin.Any?>}0:0 ()
#44	0x107fbc87c in kfun:kotlinx.coroutines#runBlocking$default(kotlin.coroutines.CoroutineContext?;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,0:0>;kotlin.Int){0§<kotlin.Any?>}0:0 ()
#45	0x107fbc87c in kfun:kotlinx.coroutines.MultiWorkerDispatcher.workerRunLoop#internal ()
#46	0x107fbc87c in kfun:kotlinx.coroutines.MultiWorkerDispatcher.<init>$lambda$1$lambda$0#internal ()
#47	0x107fbc87c in kfun:kotlinx.coroutines.MultiWorkerDispatcher.$<init>$lambda$1$lambda$0$FUNCTION_REFERENCE$5.invoke#internal ()
#48	0x107fbc87c in kfun:kotlinx.coroutines.MultiWorkerDispatcher.$<init>$lambda$1$lambda$0$FUNCTION_REFERENCE$5.$<bridge-DNN>invoke(){}#internal ()
#49	0x10948d7dc in kfun:kotlin.Function0#invoke(){}1:0-trampoline ()
#50	(null) in Worker::processQueueElement(bool) ()
#51	(null) in (anonymous namespace)::workerRoutine(void*) ()

Could you please help me find from where this crash is and how to resolve it ?

Regards,
Lyubo

@JetBrains JetBrains locked and limited conversation to collaborators Dec 18, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working crash input Touch, mouse, keyboard input related ios p:high High priority regression reproduced text
Projects
None yet
5 participants