我已经整理了一个非常简单的程序,它使用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
,则程序会出现段错误。 JSC中是否有可用的日志功能,还是我必须自己滚动?
答案 0 :(得分:20)
如果使用Mac或IOS的JavaScriptCore框架,则必须提供自己的控制台日志。
以下是一些对我有用的代码(对不起,根据您的代码,它是Objective-C而不是标准C):
JSContext *javascriptContext = [[JSContext alloc] init];
javascriptContext[@"consoleLog"] = ^(NSString *message) {
NSLog(@"Javascript log: %@",message);
};
然后你从Javascript中使用它:
consoleLog("My debug message");
请注意,我已经尝试定义了一个vararg版本(记录了多个参数)但我无法在框架api中正常工作。
请注意,此解决方案使用随新的Objective-C API引入的功能,用于与IOS 7同时引入的JavaScriptCore.framework。如果您正在寻找介绍Objective-C和Javascript之间这个良好集成的桥梁的介绍,查看Apple开发者网络上的2013 WWDC简介“将JavaScript集成到本机应用程序”会话: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");
答案 1 :(得分:14)
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");
答案 2 :(得分: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)
答案 3 :(得分:0)
您可以在Safari中调试附加到上下文的JS文件。
步骤:
1)启动Safari
2)在Safari中,通过转到“首选项” - &gt;启用“开发”菜单。 “高级” - &gt; “在菜单栏中显示开发菜单”
3)转到“开发”菜单 - &gt; “模拟器”或您的计算机名称 - &gt;选择“自动显示JSContexts的Web检查器”和“自动暂停连接到JSContexts”
4)重新运行您的项目,Safari应该自动显示Web检查器