Обновлять
Это исправлено в Xcode 8.0
Окружающая среда
Xcode 7.3.1, iPhone SE, iOS 9.3.5
Проблема
Я связал функцию C с функцией JavaScript с помощью JSObjectMakeFunctionWithCallback
с помощью JavaScriptCore framework. Если я поставлю точку останова в эту функцию C, отладчик Xcode зависнет, когда позиция выполнения придет сюда из JavaScript на JSEvaluateScript
.
- Я хочу знать причину проблемы.
- Я хочу знать подход к реализации функции C, которая правильно работает с точкой останова и может быть вызвана из среды JavaScript.
Мне не нужна идея использования Objective-C API, потому что я хочу поделиться кодом с iOS и Android.
Условие
Из своего эксперимента я получил эти условия.
- Этого не происходит в симуляторе iOS.
- Этого не происходит, когда функция JS вызывается из
JSObjectCallAsFunction
. - Это происходит, когда функция JS вызывается из
JSEvaluateScript
.
Мое мнение, глядя на стек вызовов в симуляторе, заключается в том, что эта проблема связана со встроенной сборкой JavaScriptCore JIT/LLINT. Я предполагаю, что в этих сборках не хватает чего-то, что касается механизма отладки. Поэтому я беспокоюсь, что у программиста нет решения на стороне пользователя JavaScriptCode.
Воспроизводимый исходный код
Я упаковал небольшой воспроизводимый пример в этот репозиторий.
https://github.com/omochi/jscore-debugger-hangup
шаги
- Клонируйте этот репозиторий.
- Откройте с помощью Xcode.
- Откройте
test_main.c
. - Поставьте точку останова на
printf
вTestNativeFunc
иJSEvaluateScript
вTestMain
. - Запустить приложение.
- Он остановился на
printf
. - Продолжать.
- Он остановился на
JSEvaluateScript
. - Xcode зависает.
Если вы удалите две точки останова, он запустится правильно и выведет два сообщения func
.
код
static JSValueRef TestNativeFunc(JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef* exception)
{
printf("func\n");
return JSValueMakeNull(ctx);
}
void TestMain() {
JSGlobalContextRef context = JSGlobalContextCreate(NULL);
JSObjectRef func = JSObjectMakeFunctionWithCallback(context, NULL, &TestNativeFunc);
JSValueProtect(context, func);
JSObjectCallAsFunction(context, func, NULL, 0, NULL, NULL);
JSObjectRef global_object = JSContextGetGlobalObject(context);
JSStringRef f_str = JSStringCreateWithUTF8CString("f");
JSObjectSetProperty(context, global_object, f_str, func, 0, NULL);
JSStringRef script = JSStringCreateWithUTF8CString("f();");
JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
JSStringRelease(f_str);
JSValueUnprotect(context, func);
JSGlobalContextRelease(context);
}