86
JavaScriptCore framework EZNET 熊友宏 @eskumagai http://program.station.eznet.jp/ の普通な使い

JavaScriptCore.framework の普通な使い方 #cocoa_kansai

Embed Size (px)

DESCRIPTION

Objective-C や Swift のネイティブコードから JavaScript をランタイムで実行するための JavaScriptCore.framework のお話です。基本的な機能の説明と、注意点を整理して紹介しています。

Citation preview

  • 1. JavaScriptCore framework EZ-NET @es_kumagai http://program.station.ez-net.jp/

2. @es_kumagai EZ-NET IP Phone for iPad for iPhone EZ-NET http://program.station.ez-net.jp/ 3. Xcode http://ez-net.jp/sp/xcode5/ 4. JavaScriptCore.framework 5. JavaScript 1. Web 2. 3. JavaScript 6. JavaScriptCore.framework 1. JavaScript 2. OS X 10.9iOS 7.0 7. 1. JavaScript 1. 2. 3. DL 8. 2. 1. 2. JavaScript 3. JavaScript 9. JavaScriptCore.framework 10. (1/4) JavaScriptCore import JavaScriptCore Linked Frameworks and Libraries JavaScriptCore.framework 11. (2/4) let context = JSContext() JavaScript 12. (3/4) JavaScript let script = "var value = encodeURI('');" context.evaluateScript(script) 13. (4/4) let value:JSValue = context.objectForKeyedSubscript("value") println(value.toString()) JSValue %3Cname%3E 14. JavaScriptCore.framework 15. JavaScript 16. JavaScript JavaScript context.evaluateScript(script) -> JSValue! JavaScript value;value 10 + 3;13 x = 10;x var x = 10;undened 17. JavaScript JavaScript context.objectForKeyedSubscript(name) -> JSValue! JSValue toXXXX() undened Objective-C context[name] 18. JavaScript toInt32() ->Int32 toUint32() ->Uint32 toDouble() ->Double toString() ->String! toBool() ->Bool toObject() ->AnyObject! toArray() ->[AnyObject]! toDictionary() ->[NSObject:AnyObject]! toNumber() ->NSNumber! toDate() ->NSDate! toPoint() ->CGPoint toSize() ->CGSize toRect() ->CGRect toRange() ->NSRange JSValue 19. JavaScript JSValue undefined toString() toInt32() toDouble() toBool() toObject() "undefined" 0 Double.NaN false nil 20. JavaScript JSValue null null toString() toInt32() toDouble() toBool() toObject() "null" 0 0.0 false nil 21. JavaScript isNumber() isString() isBoolean() isObject() isNull() isUndefined() JSValue 22. JavaScript 23. JavaScript JavaScript context.setObject(value,forKeyedSubscript:name) -> Void (name) (value) JavaScript Variant [object number] [object string] nil [object undened] 24. JavaScript 25. JavaScript 26. JavaScript Objective-C context[@"sum"] = ^(NSArray* values) { NSInteger result = 0; for (NSNumber* value in values) { result += value.integerValue; } return result; }; Blocks OK 27. JavaScript Swift (1/6) context.setObject(value,forKeyedSubscript:name) -> Void JSContext Objective-C Objective-C id Swift AnyObject! Swift AnyObject! 28. JavaScript Swift (2/6) Blocks Swift JSContext Objective-C Blocks 29. JavaScript Swift (3/6) #import typedef id (^unaryFunction)(id); typedef id (^binaryFunction)(id, id); @interface JSContext (Closure) - (void)setUnaryFunction:(unaryFunction)function forKeyedSubscript:(NSString*)key; - (void)setBinaryFunction:(binaryFunction)function forKeyedSubscript:(NSString*)key; @end JSContext+Closure.h 30. JavaScript Swift (4/6) - (void)setUnaryFunction:(unaryFunction)function forKeyedSubscript:(NSString*)key { [self setObject:function forKeyedSubscript:key]; } - (void)setBinaryFunction:(binaryFunction)function forKeyedSubscript:(NSString*)key { [self setObject:function forKeyedSubscript:key]; } JSContext+Closure.m 31. JavaScript Swift (5/6) #import "JSContext+Closure.h" $(PROJECT_NAME)-Bridging-Header.h "Swift Compiler - Code Generation" Objective-C Bridging Header 32. JavaScript Swift (6/6) let function = { (values:AnyObject!)->AnyObject in var sum:Int = 0 for value in values as NSArray { sum += value.integerValue } return sum } context.setUnaryFunction(function,forKeyedSubscript:"sum") JavaScript 33. JavaScript JavaScript context.evaluateScript("sum([10,20,30]);") JavaScript 34. JavaScript 35. JavaScript Case 1: #1 context.evaluateScript( "var tag='';n var val=encodeURI(tag);") [OK] 36. JavaScript Case 2: #2 context.evaluateScript( "var tag=''; var val=nencodeURI(tag);") JavaScript [OK] 37. JavaScript Case 3: #1 context.evaluateScript( "var tag='';") context.evaluateScript( "var val=encodeURI(tag);") [OK] 38. JavaScript Case 4: #2 context.evaluateScript( "var tag=''; var val=") context.evaluateScript( "encodeURI(tag);") evaluateScript SyntaxError: Unexpected EOF [NG] 39. JavaScript Case 5: #3 context.evaluateScript("if (value==1)") context.evaluateScript("{ (text="Yes") }") context.evaluateScript("else") context.evaluateScript("{ (text="No") }") evaluateScript OK [NG] 40. JavaScript Case 6: #4 context.evaluateScript("try {") context.evaluateScript("value=XXXX;") context.evaluateScript("} catch (e)") context.evaluateScript({ value=0; }") evaluateScript OK [NG] 41. JavaScript JavaScript 42. JavaScript 43. JavaScript evaluateScript JavaScript 44. JavaScript JavaScript Error SyntaxError TypeError EvalError RangeError ReferenceError URIError 45. JavaScript JavaScript 46. exceptionHandler JavaScript JavaScript context.exceptionHandler :((JSContext!,JSValue!)->Void)! 47. context: JSContext exception: JavaScript exceptionHandler context.exceptionHandler = { (context:JSContext!, exception:JSValue!)->Void in println("Error: (exception.toString())") }; 48. JavaScript exception .toString() "SyntaxError: Expected token ':'" .toDictionary()["line"] as? NSNumber evaluateScript .toDictionary()["stack"] as? NSString nil 49. JavaScript exception Error 50. JavaScript Error exceptionHandler "Error: message" JavaScript JavaScript context.evaluateScript("throw Error(message);") 51. "MyError: message" JavaScript context.evaluateScript( "var error=Error();" + "error.name='MyError';" + "error.message='message';" + "throw error;") 52. JavaScriptCore.framework 53. 1. JavaScript 2. 3. JavaScript 4. JavaScript 54. JavaScript 55. JavaScript JSExport import JavaScriptCore @objc protocol EZObjectJSExport: JSExport { var name:String { get set } var value:String { get set } func set(name:String, _ value:String)->Void func toData()->NSData } @objc 56. JavaScript public class EZObject: NSObject, EZObjectJSExport { public override init() { } public var name:String { } public var value:String { } public func set(name:String, _ value:String)->Void { } public func toData()->NSData { } } NSObject 57. JavaScript "TypeError: 'undened' is not a function" "undened" JSExport JavaScript JavaScript 58. 1. 2. JavaScript 59. JavaScript let object = EZObject() context.setObject(object, forKeyedSubscript:"obj") 60. @objc protocol EZObjectJSExport: JSExport { class func create()->AnyObject } public class EZObject: NSObject, EZObjectJSExport { public class func create() -> AnyObject { return EZObject(); } } JavaScript 61. JavaScript context.setObject(EZObject.self, forKeyedSubscript:"EZObject") context.evaluateScript("var obj=EZObject.create();") 62. JavaScript let object = context.objectForKeyedSubscript("obj") .toObject() as EZObject 63. JavaScript 64. JavaScript JavaScript context.evaluateScript("var name = obj.name;") context.evaluateScript("obj.value = 'NewValue';") "Type Error: 'PROP' is not a function" 65. JavaScript 66. JavaScript JavaScript context.evaluateScript("obj.set('NewName','NewValue');") context.evaluateScript("var data = obj.toData();") 67. 68. JavaScript #1 JavaScript toString() (Beta 5) toString() 69. JavaScript #2 Swift func set(name:String, value:String)->Void void setValue(name, value) func set(#name:String, value:String)->Void void setWithNameValue(name, value) func set(name:String, _ value:String)->Void void set(name, value) 70. JavaScriptCore.framework JavaScript 71. JavaScript JavaScript 72. JavaScript JavaScript JavaScript context.evaluateScript("function sum(array) { }") let sum = context.objectForKeyedSubscript("sum") let result = sum.callWithArguments([ [1,3,5,7] ]) 73. JavaScript JavaScript 74. JavaScript JavaScript let object = EZObject() context.setObject(object, forKeyedSubscript:"obj") context.setObject(EZObject.self, forKeyedSubscript:"EZObject") context.evaluateScript("var obj=EZObject.create();") let object = context.objectForKeyedSubscript("obj") 75. 76. JavaScript JavaScript context.evaluateScript("obj.value = 'FromJS';") println(object.value) 77. JavaScript JavaScript object.value = "FromNative" context.evaluateScript("var value=obj.value;") let value = context.objectForKeyedSubscript("value") println(value) 78. JavaScriptCore.framework 79. 80. var bundle = NSBundle.mainBundle() var path = bundle.pathForResource("Script",ofType:"js") let script = NSString(contentsOfFile:path, encoding:NSUTF8StringEncoding, error: nil) context.evaluateScript(script) let result = context.objectForKeyedSubscript("answer") 81. function sum(array) { var result = 0; for (var i = 0; i < array.length; ++i) { result += array[i]; } return result; } var answer = sum([1,10,100,1000]); JavaScript 82. return 83. function sum(array) { var result = 0; for (var i = 0; i < array.length; ++i) { result += array[i]; } return result; } return sum([1,10,100,1000]); return JavaScript return 84. SyntaxError: Return statements are only valid inside functions return 85. return let result = context.evaluateScript("(function(){(script)})();") return 86. JavaScriptCore.framework JavaScript JavaScript JavaScript