JavaScriptCore console.log
Я собрал очень простую программу, которая использует JavaScriptCore для оценки JS:
#import <CoreFoundation/CoreFoundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
int main(int argc, const char * argv[])
{
JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);
FILE *f = fopen(argv[1],"r");
char * buffer = malloc(10000000);
fread(buffer,1,10000000,f);
CFStringRef strs = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingASCII);
JSStringRef jsstr = JSStringCreateWithCFString(strs);
JSValueRef result = JSEvaluateScript(ctx, jsstr, NULL, NULL, 0, NULL);
double res = JSValueToNumber(ctx, result, NULL);
JSGlobalContextRelease(ctx);
printf("%lf\n", res);
return 0;
}
Идея здесь в том, что последним значением считается Number
, и это значение печатается. Это работает для действительного кода javascript, например
var square = function(x) { return x*x; }; square(4)
Однако, если код пытается выполнить console.log
, программа segfaults. Есть ли функция журнала, доступная в АО, или мне нужно сворачивать самостоятельно?
Ответы
Ответ 1
Вам нужно предоставить свой собственный консольный журнал, если вы используете фреймворк JavaScriptCore с Mac или IOS.
Вот код, который работал у меня (извините, это Objective-C, а не стандартный C в соответствии с вашим кодом выше):
JSContext *javascriptContext = [[JSContext alloc] init];
javascriptContext[@"consoleLog"] = ^(NSString *message) {
NSLog(@"Javascript log: %@",message);
};
Затем вы используете его из Javascript:
consoleLog("My debug message");
Обратите внимание, что я попытался определить версию vararg (log с несколькими параметрами), но я не мог заставить это работать правильно в рамках api.
Обратите внимание, что это решение использует функции, введенные с новым API Objective-C для JavaScriptCore.framework, представленного одновременно с IOS 7. Если вы ищете введение в этот хорошо интегрированный мост между Objective-C и Javascript, ознакомьтесь с вступительным словом сессии WWDC 2013 года "Интеграция JavaScript в родные приложения" в сети Apple developer: https://developer.apple.com/videos/wwdc/2013/?id=615
Обновить для ответа:
Для тех из вас, кто хочет максимизировать повторное использование кода javascript без рефакторинга, мне удалось получить версию, которая объявляет журнал формы console.log():
JSContext *javascriptContext = [[JSContext alloc] init];
[javascriptContext evaluateScript:@"var console = {}"];
javascriptContext[@"console"][@"log"] = ^(NSString *message) {
NSLog(@"Javascript log: %@",message);
};
Затем вы используете его из Javascript:
console.log("My debug message");
Ответ 2
Swift 3.0
let javascriptContext = JSContext()
javascriptContext?.evaluateScript("var console = { log: function(message) { _consoleLog(message) } }")
let consoleLog: @convention(block) (String) -> Void = { message in
print("console.log: " + message)
}
javascriptContext?.setObject(unsafeBitCast(consoleLog, to: AnyObject.self), forKeyedSubscript: "_consoleLog" as (NSCopying & NSObjectProtocol)!)
Swift 2.1
let javascriptContext = JSContext()
javascriptContext.evaluateScript("var console = { log: function(message) { _consoleLog(message) } }")
let consoleLog: @convention(block) String -> Void = { message in
print("console.log: " + message)
}
javascriptContext.setObject(unsafeBitCast(consoleLog, AnyObject.self), forKeyedSubscript: "_consoleLog")
Затем вы используете его из Javascript:
console.log("My debug message");
Ответ 3
self.jsContext = JSContext()
self.jsContext.evaluateScript(...)
let logFunction: @convention(block) (String) -> Void = { (string: String) in
print(string)
}
self.jsContext.setObject(logFunction, forKeyedSubscript: "consoleLog" as NSCopying & NSObjectProtocol)
Ответ 4
Вы можете отлаживать JS файл, прикрепленный к контексту в Safari.
Шаги:
1) Запустить Safari
2) В Safari включите меню "Разработка", перейдя в "Настройки" → "Дополнительно" → "Показать меню разработчика в строке меню"
3) Перейдите в меню "Разработка" → "Симулятор" или название вашего компьютера → выберите "Автоматически показать веб-инспектор для JSContexts" и "Автоматически приостановить подключение к JSContexts"
4) Повторно запустите проект, и Safari должен автоматически показать веб-инспектора