├── podfile ├── Pods ├── Headers │ ├── Public │ │ └── JSPatch │ │ │ └── JPEngine.h │ └── Private │ │ └── JSPatch │ │ └── JPEngine.h ├── Target Support Files │ ├── JSPatch │ │ ├── JSPatch-prefix.pch │ │ ├── JSPatch-dummy.m │ │ └── JSPatch.xcconfig │ └── Pods │ │ ├── Pods-dummy.m │ │ ├── Pods.debug.xcconfig │ │ ├── Pods.release.xcconfig │ │ ├── Pods-acknowledgements.markdown │ │ ├── Pods-acknowledgements.plist │ │ ├── Pods-frameworks.sh │ │ └── Pods-resources.sh ├── Manifest.lock ├── Pods.xcodeproj │ ├── xcuserdata │ │ └── meiqing.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ ├── Pods.xcscheme │ │ │ └── JSPatch.xcscheme │ └── project.pbxproj └── JSPatch │ ├── LICENSE │ ├── JSPatch │ ├── JPEngine.h │ ├── JSPatch.js │ └── JPEngine.m │ └── README-CN.md ├── readme ├── README.md ├── JsPatchDemo.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── meiqing.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── JsPatchDemo.xcscheme └── project.pbxproj ├── Podfile.lock ├── JsPatchDemo ├── ViewController.h ├── AppDelegate.h ├── main.m ├── mq.js ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── Info.plist ├── ViewController.m └── AppDelegate.m ├── JsPatchDemo.xcworkspace └── contents.xcworkspacedata ├── JsPatchDemoTests ├── Info.plist └── JsPatchDemoTests.m └── JsPatchDemoUITests ├── Info.plist └── JsPatchDemoUITests.m /podfile: -------------------------------------------------------------------------------- 1 | platform:ios,'6.0' 2 | pod 'JSPatch' 3 | -------------------------------------------------------------------------------- /Pods/Headers/Public/JSPatch/JPEngine.h: -------------------------------------------------------------------------------- 1 | ../../../JSPatch/JSPatch/JPEngine.h -------------------------------------------------------------------------------- /Pods/Headers/Private/JSPatch/JPEngine.h: -------------------------------------------------------------------------------- 1 | ../../../JSPatch/JSPatch/JPEngine.h -------------------------------------------------------------------------------- /Pods/Target Support Files/JSPatch/JSPatch-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/JSPatch/JSPatch-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_JSPatch : NSObject 3 | @end 4 | @implementation PodsDummy_JSPatch 5 | @end 6 | -------------------------------------------------------------------------------- /readme: -------------------------------------------------------------------------------- 1 | Installation 2 | 3 | # Your Podfile 4 | platform :ios, '6.0' 5 | pod 'JSPatch' 6 | 7 | Manually 8 | 9 | Copy JSEngine.m JSEngine.h JSPatch.js in JSPatch/ to your project. 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSPatchDemo 2 | Fix bugs without update versions 3 | 4 | # Installation 5 | 6 | platform :ios, '6.0' 7 | pod 'JSPatch' 8 | 9 | # Manually 10 | Copy JSEngine.m JSEngine.h JSPatch.js in JSPatch/ to your project. 11 | -------------------------------------------------------------------------------- /JsPatchDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - JSPatch (0.1.5): 3 | - JSPatch/Core (= 0.1.5) 4 | - JSPatch/Core (0.1.5) 5 | 6 | DEPENDENCIES: 7 | - JSPatch 8 | 9 | SPEC CHECKSUMS: 10 | JSPatch: 405b5f5990643e6717dd6715ac60d6a2b582a6ba 11 | 12 | COCOAPODS: 0.39.0 13 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - JSPatch (0.1.5): 3 | - JSPatch/Core (= 0.1.5) 4 | - JSPatch/Core (0.1.5) 5 | 6 | DEPENDENCIES: 7 | - JSPatch 8 | 9 | SPEC CHECKSUMS: 10 | JSPatch: 405b5f5990643e6717dd6715ac60d6a2b582a6ba 11 | 12 | COCOAPODS: 0.39.0 13 | -------------------------------------------------------------------------------- /JsPatchDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // JsPatchDemo 4 | // 5 | // Created by meiqing on 15/12/12. 6 | // Copyright © 2015年 meiqing. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /JsPatchDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /JsPatchDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JsPatchDemo 4 | // 5 | // Created by meiqing on 15/12/12. 6 | // Copyright © 2015年 meiqing. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Pods/Target Support Files/JSPatch/JSPatch.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/JSPatch" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/JSPatch" 3 | OTHER_LDFLAGS = -framework "Foundation" -weak_framework "JavaScriptCore" 4 | PODS_ROOT = ${SRCROOT} 5 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /JsPatchDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JsPatchDemo 4 | // 5 | // Created by meiqing on 15/12/12. 6 | // Copyright © 2015年 meiqing. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/JSPatch" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/JSPatch" 4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"JSPatch" -framework "Foundation" -weak_framework "JavaScriptCore" 5 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/JSPatch" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/JSPatch" 4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"JSPatch" -framework "Foundation" -weak_framework "JavaScriptCore" 5 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /JsPatchDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /JsPatchDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/meiqing.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JSPatch.xcscheme 8 | 9 | isShown 10 | 11 | 12 | Pods.xcscheme 13 | 14 | isShown 15 | 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 21A48DB9FD0DC3162F4466E6D11E704D 21 | 22 | primary 23 | 24 | 25 | FD1D53461DE538B7C8DFE0B76D857587 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /JsPatchDemo.xcodeproj/xcuserdata/meiqing.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JsPatchDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | BFA571861C1C2D170044AAB4 16 | 17 | primary 18 | 19 | 20 | BFA5719F1C1C2D170044AAB4 21 | 22 | primary 23 | 24 | 25 | BFA571AA1C1C2D170044AAB4 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /JsPatchDemo/mq.js: -------------------------------------------------------------------------------- 1 | 2 | defineClass("ViewController", { 3 | 4 | tableView_cellForRowAtIndexPath: function(tableView, indexPath) { 5 | var cell = tableView.dequeueReusableCellWithIdentifier("cell") 6 | if (!cell) { 7 | cell = require('UITableViewCell').alloc().initWithStyle_reuseIdentifier(0, "cell") 8 | } 9 | cell.textLabel().setText("meijiaqing"); 10 | var redColor = require('UIColor').redColor(); 11 | cell.setBackgroundColor(redColor); 12 | return cell 13 | }, 14 | 15 | //instance method definitions 16 | tableView_didSelectRowAtIndexPath: function(tableView, indexPath) { 17 | var row = indexPath.row() 18 | if (self.dataSource().length > row) { // 加上判断越界的逻辑 19 | var content = self.dataArr()[row]; 20 | } 21 | } 22 | }, {}); -------------------------------------------------------------------------------- /JsPatchDemoTests/JsPatchDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JsPatchDemoTests.m 3 | // JsPatchDemoTests 4 | // 5 | // Created by meiqing on 15/12/12. 6 | // Copyright © 2015年 meiqing. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JsPatchDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JsPatchDemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Pods/JSPatch/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 bang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## JSPatch 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2015 bang 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | 29 | Generated by CocoaPods - http://cocoapods.org 30 | -------------------------------------------------------------------------------- /JsPatchDemoUITests/JsPatchDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JsPatchDemoUITests.m 3 | // JsPatchDemoUITests 4 | // 5 | // Created by meiqing on 15/12/12. 6 | // Copyright © 2015年 meiqing. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JsPatchDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JsPatchDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /JsPatchDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /JsPatchDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /JsPatchDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /JsPatchDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /JsPatchDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // JsPatchDemo 4 | // 5 | // Created by meiqing on 15/12/12. 6 | // Copyright © 2015年 meiqing. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | @property(nonatomic,strong)UITableView* mytableView; 13 | @property(nonatomic,strong)NSArray *dataSource; 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad 19 | { 20 | 21 | UITableView* tv = [[UITableView alloc]initWithFrame:self.view.bounds 22 | style:UITableViewStylePlain]; 23 | self.mytableView = tv; 24 | self.mytableView.delegate = self; 25 | self.mytableView.dataSource = self; 26 | [self.view addSubview:self.mytableView]; 27 | 28 | } 29 | 30 | #pragma mark -- UITableViewDataSource 31 | 32 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 33 | { 34 | return 3; 35 | } 36 | 37 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 38 | { 39 | static NSString* i= @"cell"; 40 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:i]; 41 | if (cell == nil ) { 42 | cell =[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault 43 | reuseIdentifier:i]; 44 | } 45 | //我在这里给cell的标题是"meiqing",通过JS修改成了"meijiaqing" 46 | cell.textLabel.text = @"meiqing"; 47 | //我在这里给cell的背景颜色是白色,但是上线后发现红色更好看,我就在JS里写了红色。 48 | cell.backgroundColor = [UIColor whiteColor]; 49 | return cell; 50 | } 51 | 52 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 53 | { 54 | self.dataSource = @[@"1",@"2"]; 55 | // cell有三行,当我点击第三行的时候肯定会数组越界导致 crash 56 | // 还好我在JS里弥补了这个bug,详情请看JS里的处理 57 | NSString *content = self.dataSource[indexPath.row]; 58 | NSLog(@"content = %@",content); 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2015 bang 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | 40 | Title 41 | JSPatch 42 | Type 43 | PSGroupSpecifier 44 | 45 | 46 | FooterText 47 | Generated by CocoaPods - http://cocoapods.org 48 | Title 49 | 50 | Type 51 | PSGroupSpecifier 52 | 53 | 54 | StringsTable 55 | Acknowledgements 56 | Title 57 | Acknowledgements 58 | 59 | 60 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/meiqing.xcuserdatad/xcschemes/Pods.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/meiqing.xcuserdatad/xcschemes/JSPatch.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /JsPatchDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JsPatchDemo 4 | // 5 | // Created by meiqing on 15/12/12. 6 | // Copyright © 2015年 meiqing. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "JPEngine.h" 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | 20 | [JPEngine startEngine]; 21 | NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"mq" ofType:@"js"]; 22 | NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil]; 23 | [JPEngine evaluateScript:script]; 24 | 25 | [self.window makeKeyAndVisible]; 26 | 27 | return YES; 28 | } 29 | 30 | - (void)applicationWillResignActive:(UIApplication *)application { 31 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 32 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 33 | } 34 | 35 | - (void)applicationDidEnterBackground:(UIApplication *)application { 36 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | - (void)applicationWillEnterForeground:(UIApplication *)application { 41 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | - (void)applicationWillTerminate:(UIApplication *)application { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Pods/JSPatch/JSPatch/JPEngine.h: -------------------------------------------------------------------------------- 1 | // 2 | // JPEngine.h 3 | // JSPatch 4 | // 5 | // Created by bang on 15/4/30. 6 | // Copyright (c) 2015 bang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface JPEngine : NSObject 14 | 15 | /*! 16 | @method 17 | @discussion start the JSPatch engine, execute only once. 18 | */ 19 | + (void)startEngine; 20 | 21 | /*! 22 | @method 23 | @description Evaluate Javascript code from a file Path. Call it after +startEngine. 24 | @param filePath: The filePath of the Javascript code. 25 | @result The last value generated by the script. 26 | */ 27 | + (JSValue *)evaluateScriptWithPath:(NSString *)filePath; 28 | 29 | /*! 30 | @method 31 | @description Evaluate a string of JavaScript code. Call it after +startEngine. 32 | The method will generate a default resouceURL named "main.js" to the Safari debugger. 33 | @param script: A string containing the JavaScript code to evaluate. 34 | @result The last value generated by the script. 35 | */ 36 | + (JSValue *)evaluateScript:(NSString *)script; 37 | 38 | /*! 39 | @method 40 | @description Return the JSPatch JavaScript execution environment. 41 | */ 42 | + (JSContext *)context; 43 | 44 | 45 | 46 | /*! 47 | @method 48 | @description Add JPExtension. 49 | @param extensions: An array containing class name string. 50 | */ 51 | + (void)addExtensions:(NSArray *)extensions; 52 | 53 | /*! 54 | @method 55 | @description add new struct type supporting to JS 56 | @param defineDict: the definition of struct, for Example: 57 | @{ 58 | @"name": @"CGAffineTransform", //struct name 59 | @"types": @"ffffff", //struct types 60 | @"keys": @[@"a", @"b", @"c", @"d", @"tx", @"ty"] //struct keys in JS 61 | } 62 | */ 63 | + (void)defineStruct:(NSDictionary *)defineDict; 64 | 65 | /*! 66 | @method 67 | @description Return the registered struct definition in JSPatch, 68 | the key of dictionary is the struct name. 69 | */ 70 | + (NSMutableDictionary *)registeredStruct; 71 | @end 72 | 73 | 74 | 75 | @interface JPExtension : NSObject 76 | + (void)main:(JSContext *)context; 77 | 78 | + (void *)formatPointerJSToOC:(JSValue *)val; 79 | + (id)formatPointerOCToJS:(void *)pointer; 80 | + (id)formatJSToOC:(JSValue *)val; 81 | + (id)formatOCToJS:(id)obj; 82 | 83 | + (int)sizeOfStructTypes:(NSString *)structTypes; 84 | + (void)getStructDataWidthDict:(void *)structData dict:(NSDictionary *)dict structDefine:(NSDictionary *)structDefine; 85 | + (NSDictionary *)getDictOfStruct:(void *)structData structDefine:(NSDictionary *)structDefine; 86 | @end 87 | 88 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | -------------------------------------------------------------------------------- /JsPatchDemo.xcodeproj/xcuserdata/meiqing.xcuserdatad/xcschemes/JsPatchDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | realpath() { 12 | DIRECTORY="$(cd "${1%/*}" && pwd)" 13 | FILENAME="${1##*/}" 14 | echo "$DIRECTORY/$FILENAME" 15 | } 16 | 17 | install_resource() 18 | { 19 | case $1 in 20 | *.storyboard) 21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 23 | ;; 24 | *.xib) 25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 27 | ;; 28 | *.framework) 29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 33 | ;; 34 | *.xcdatamodel) 35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 37 | ;; 38 | *.xcdatamodeld) 39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 41 | ;; 42 | *.xcmappingmodel) 43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 45 | ;; 46 | *.xcassets) 47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") 48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 49 | ;; 50 | /*) 51 | echo "$1" 52 | echo "$1" >> "$RESOURCES_TO_COPY" 53 | ;; 54 | *) 55 | echo "${PODS_ROOT}/$1" 56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 57 | ;; 58 | esac 59 | } 60 | if [[ "$CONFIGURATION" == "Debug" ]]; then 61 | install_resource "JSPatch/JSPatch/JSPatch.js" 62 | fi 63 | if [[ "$CONFIGURATION" == "Release" ]]; then 64 | install_resource "JSPatch/JSPatch/JSPatch.js" 65 | fi 66 | 67 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 68 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 69 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 70 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 71 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 72 | fi 73 | rm -f "$RESOURCES_TO_COPY" 74 | 75 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 76 | then 77 | case "${TARGETED_DEVICE_FAMILY}" in 78 | 1,2) 79 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 80 | ;; 81 | 1) 82 | TARGET_DEVICE_ARGS="--target-device iphone" 83 | ;; 84 | 2) 85 | TARGET_DEVICE_ARGS="--target-device ipad" 86 | ;; 87 | *) 88 | TARGET_DEVICE_ARGS="--target-device mac" 89 | ;; 90 | esac 91 | 92 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 93 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 94 | while read line; do 95 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 96 | XCASSET_FILES+=("$line") 97 | fi 98 | done <<<"$OTHER_XCASSETS" 99 | 100 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 101 | fi 102 | -------------------------------------------------------------------------------- /Pods/JSPatch/JSPatch/JSPatch.js: -------------------------------------------------------------------------------- 1 | var global = this 2 | 3 | ;(function() { 4 | 5 | var callbacks = {} 6 | var callbackID = 0 7 | 8 | var _formatOCToJS = function(obj) { 9 | if (obj === undefined || obj === null) return false 10 | if (typeof obj == "object") { 11 | if (obj.__obj) return obj 12 | if (obj.__isNil) return false 13 | } 14 | if (obj instanceof Array) { 15 | var ret = [] 16 | obj.forEach(function(o) { 17 | ret.push(_formatOCToJS(o)) 18 | }) 19 | return ret 20 | } 21 | if (obj instanceof Function) { 22 | return function() { 23 | var args = Array.prototype.slice.call(arguments) 24 | var formatedArgs = _OC_formatJSToOC(args) 25 | for (var i = 0; i < args.length; i++) { 26 | if (args[i] === null || args[i] === undefined || args[i] === false) { 27 | formatedArgs.splice(i, 1, undefined) 28 | } else if (args[i] == nsnull) { 29 | formatedArgs.splice(i, 1, null) 30 | } 31 | } 32 | return _OC_formatOCToJS(obj.apply(obj, formatedArgs)) 33 | } 34 | } 35 | if (obj instanceof Object) { 36 | var ret = {} 37 | for (var key in obj) { 38 | ret[key] = _formatOCToJS(obj[key]) 39 | } 40 | return ret 41 | } 42 | return obj 43 | } 44 | 45 | var _methodFunc = function(instance, clsName, methodName, args, isSuper, isPerformSelector) { 46 | var selectorName = methodName 47 | if (!isPerformSelector) { 48 | methodName = methodName.replace(/__/g, "-") 49 | selectorName = methodName.replace(/_/g, ":").replace(/-/g, "_") 50 | var marchArr = selectorName.match(/:/g) 51 | var numOfArgs = marchArr ? marchArr.length : 0 52 | if (args.length > numOfArgs) { 53 | selectorName += ":" 54 | } 55 | } 56 | var ret = instance ? _OC_callI(instance, selectorName, args, isSuper): 57 | _OC_callC(clsName, selectorName, args) 58 | return _formatOCToJS(ret) 59 | } 60 | 61 | Object.defineProperty(Object.prototype, "__c", {value: function(methodName) { 62 | if (this instanceof Boolean) { 63 | return function() { 64 | return false 65 | } 66 | } 67 | 68 | if (!this.__obj && !this.__clsName) { 69 | if (!this[methodName]) { 70 | throw new Error(this + '.' + methodName + ' is undefined') 71 | } 72 | return this[methodName].bind(this); 73 | } 74 | 75 | var self = this 76 | if (methodName == 'super') { 77 | return function() { 78 | return {__obj: self.__obj, __clsName: self.__clsName, __isSuper: 1} 79 | } 80 | } 81 | 82 | if (methodName.indexOf('performSelector') > -1) { 83 | if (methodName == 'performSelector') { 84 | return function(){ 85 | var args = Array.prototype.slice.call(arguments) 86 | return _methodFunc(self.__obj, self.__clsName, args[0], args.splice(1), self.__isSuper, true) 87 | } 88 | } else if (methodName == 'performSelectorInOC') { 89 | return function(){ 90 | var args = Array.prototype.slice.call(arguments) 91 | return {__isPerformInOC:1, obj:self.__obj, clsName:self.__clsName, sel: args[0], args: args[1], cb: args[2]} 92 | } 93 | } 94 | } 95 | return function(){ 96 | var args = Array.prototype.slice.call(arguments) 97 | return _methodFunc(self.__obj, self.__clsName, methodName, args, self.__isSuper) 98 | } 99 | }, configurable:false, enumerable: false}) 100 | 101 | var _require = function(clsName) { 102 | if (!global[clsName]) { 103 | global[clsName] = { 104 | __clsName: clsName 105 | } 106 | } 107 | return global[clsName] 108 | } 109 | 110 | global.require = function(clsNames) { 111 | var lastRequire 112 | clsNames.split(',').forEach(function(clsName) { 113 | lastRequire = _require(clsName.trim()) 114 | }) 115 | return lastRequire 116 | } 117 | 118 | var _formatDefineMethods = function(methods, newMethods) { 119 | for (var methodName in methods) { 120 | (function(){ 121 | var originMethod = methods[methodName] 122 | newMethods[methodName] = [originMethod.length, function() { 123 | var args = _formatOCToJS(Array.prototype.slice.call(arguments)) 124 | var lastSelf = global.self 125 | var ret; 126 | try { 127 | global.self = args[0] 128 | args.splice(0,1) 129 | ret = originMethod.apply(originMethod, args) 130 | global.self = lastSelf 131 | } catch(e) { 132 | _OC_catch(e.message, e.stack) 133 | } 134 | return ret 135 | }] 136 | })() 137 | } 138 | } 139 | 140 | global.defineClass = function(declaration, instMethods, clsMethods) { 141 | var newInstMethods = {}, newClsMethods = {} 142 | _formatDefineMethods(instMethods, newInstMethods) 143 | _formatDefineMethods(clsMethods, newClsMethods) 144 | 145 | var ret = _OC_defineClass(declaration, newInstMethods, newClsMethods) 146 | 147 | return require(ret["cls"]) 148 | } 149 | 150 | global.block = function(args, cb) { 151 | var slf = this 152 | if (args instanceof Function) { 153 | cb = args 154 | args = '' 155 | } 156 | var callback = function() { 157 | var args = Array.prototype.slice.call(arguments) 158 | return cb.apply(slf, _formatOCToJS(args)) 159 | } 160 | return {args: args, cb: callback, __isBlock: 1} 161 | } 162 | 163 | if (global.console) { 164 | var jsLogger = console.log; 165 | global.console.log = function() { 166 | global._OC_log.apply(global, arguments); 167 | if (jsLogger) { 168 | jsLogger.apply(global.console, arguments); 169 | } 170 | } 171 | } else { 172 | global.console = { 173 | log: global._OC_log 174 | } 175 | } 176 | 177 | global.YES = 1 178 | global.NO = 0 179 | global.nsnull = _OC_null 180 | global._formatOCToJS = _formatOCToJS 181 | 182 | })() -------------------------------------------------------------------------------- /Pods/JSPatch/README-CN.md: -------------------------------------------------------------------------------- 1 | # JSPatch 2 | 3 | JSPatch 可以让你用 JavaScript 书写原生 iOS APP。只需在项目引入极小的引擎,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,获得脚本语言的优势:为项目动态添加模块,或替换项目原生代码动态修复 bug。 4 | 5 | 项目仍在开发中,欢迎一起完善这个项目。 6 | 7 | ## 示例 8 | 9 | ```objc 10 | @implementation AppDelegate 11 | 12 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 13 | { 14 | [JPEngine startEngine]; 15 | NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"]; 16 | NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil]; 17 | [JPEngine evaluateScript:script]; 18 | 19 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 20 | [self.window addSubview:[self genView]]; 21 | [self.window makeKeyAndVisible]; 22 | 23 | return YES; 24 | } 25 | 26 | - (UIView *)genView 27 | { 28 | return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)]; 29 | } 30 | 31 | @end 32 | ``` 33 | 34 | ```js 35 | // demo.js 36 | require('UIView, UIColor, UILabel') 37 | defineClass('AppDelegate', { 38 | // replace the -genView method 39 | genView: function() { 40 | var view = self.ORIGgenView(); 41 | view.setBackgroundColor(UIColor.greenColor()) 42 | var label = UILabel.alloc().initWithFrame(view.frame()); 43 | label.setText("JSPatch"); 44 | label.setTextAlignment(1); 45 | view.addSubview(label); 46 | return view; 47 | } 48 | }); 49 | ``` 50 | 51 | 52 | ## 安装 53 | 54 | 拷贝 `JSPatch/` 目录下的三个文件 `JSEngine.m` / `JSEngine.h` / `JSPatch.js` 到项目里即可。 55 | 56 | ## 使用 57 | 58 | ### Objective-C: 59 | 1. `#import "JPEngine.h"` 60 | 2. 调用`[JPEngine startEngine]` 61 | 3. 通过`[JPEngine evaluateScript:@""]`接口执行 JavaScript。 62 | 63 | ```objc 64 | [JPEngine startEngine]; 65 | 66 | // 直接执行js 67 | [JPEngine evaluateScript:@"\ 68 | var alertView = require('UIAlertView').alloc().init();\ 69 | alertView.setTitle('Alert');\ 70 | alertView.setMessage('AlertView from js'); \ 71 | alertView.addButtonWithTitle('OK');\ 72 | alertView.show(); \ 73 | "]; 74 | 75 | // 从网络拉回js脚本执行 76 | [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://cnbang.net/test.js"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 77 | NSString *script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 78 | [JPEngine evaluateScript:script]; 79 | }]; 80 | 81 | // 执行本地js文件 82 | NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"js"]; 83 | NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil]; 84 | [JPEngine evaluateScript:script]; 85 | ``` 86 | 87 | ### JavaScript: 88 | 89 | #### 基础使用方式 90 | 91 | ```js 92 | // 调用require引入要使用的OC类 93 | require('UIView, UIColor, UISlider, NSIndexPath') 94 | 95 | // 调用类方法 96 | var redColor = UIColor.redColor(); 97 | 98 | // 调用实例方法 99 | var view = UIView.alloc().init(); 100 | view.setNeedsLayout(); 101 | 102 | // set proerty 103 | view.setBackgroundColor(redColor); 104 | 105 | // get property 106 | var bgColor = view.backgroundColor(); 107 | 108 | // 多参数方法名用'_'隔开: 109 | // OC:NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1]; 110 | var indexPath = NSIndexPath.indexPathForRow_inSection(0, 1); 111 | 112 | // 方法名包含下划线'_',js用双下划线表示 113 | // OC: [JPObject _privateMethod]; 114 | JPObject.__privateMethod() 115 | 116 | // 如果要把 `NSArray` / `NSString` / `NSDictionary` 转为对应的 JS 类型,使用 `.toJS()` 接口. 117 | var arr = require('NSMutableArray').alloc().init() 118 | arr.addObject("JS") 119 | jsArr = arr.toJS() 120 | console.log(jsArr.push("Patch").join('')) //output: JSPatch 121 | 122 | // 在JS用字典的方式表示 CGRect / CGSize / CGPoint / NSRange 123 | var view = UIView.alloc().initWithFrame({x:20, y:20, width:100, height:100}); 124 | var x = view.bounds.x; 125 | 126 | // block 从 JavaScript 传入 Objective-C 时,需要写上每个参数的类型。 127 | // OC Method: + (void)request:(void(^)(NSString *content, BOOL success))callback 128 | require('JPObject').request(block("NSString *, BOOL", function(ctn, succ) { 129 | if (succ) log(ctn) 130 | })); 131 | 132 | // GCD 133 | dispatch_after(function(1.0, function(){ 134 | // do something 135 | })) 136 | dispatch_async_main(function(){ 137 | // do something 138 | }) 139 | ``` 140 | 141 | 详细文档请参考wiki页面:[Base Usage](https://github.com/bang590/JSPatch/wiki/Base-usage) 142 | 143 | 144 | #### 定义类/替换方法 145 | 146 | 用 `defineClass()` 定义 Objective-C 的类,对类和实例方法进行动态替换。 147 | 148 | ```objc 149 | // OC 150 | @implementation JPTableViewController 151 | ... 152 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 153 | { 154 | NSString *content = self.dataSource[[indexPath row]]; //may cause out of bound 155 | JPViewController *ctrl = [[JPViewController alloc] initWithContent:content]; 156 | [self.navigationController pushViewController:ctrl]; 157 | } 158 | - (NSArray *)dataSource 159 | { 160 | return @[@"JSPatch", @"is"]; 161 | } 162 | - (void)customMethod 163 | { 164 | NSLog(@"callCustom method") 165 | } 166 | @end 167 | ``` 168 | 169 | ```objc 170 | // JS 171 | defineClass("JPTableViewController", { 172 | // instance method definitions 173 | tableView_didSelectRowAtIndexPath: function(tableView, indexPath) { 174 | var row = indexPath.row() 175 | if (self.dataSource().count() > row) { //fix the out of bound bug here 176 | var content = self.dataSource().objectAtIndex(row); 177 | var ctrl = JPViewController.alloc().initWithContent(content); 178 | self.navigationController().pushViewController(ctrl); 179 | } 180 | }, 181 | 182 | dataSource: function() { 183 | // get the original method by adding prefix 'ORIG' 184 | var data = self.ORIGdataSource().toJS(); 185 | return data.push('Good!'); 186 | } 187 | }, {}) 188 | ``` 189 | 190 | 详细文档请参考wiki页面:[Usage of defineClass](https://github.com/bang590/JSPatch/wiki/Usage-of-defineClass) 191 | 192 | 193 | #### 扩展 194 | 195 | 一些自定义的struct类型、C函数调用以及其他功能可以通过扩展实现,调用 `+addExtensions:` 可以加载扩展接口: 196 | 197 | ```objc 198 | @implementation AppDelegate 199 | 200 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 201 | { 202 | [JPEngine startEngine]; 203 | 204 | //添加扩展 205 | [JPEngine addExtensions:@[@"JPInclude", @"JPCGTransform"]]; 206 | 207 | NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"]; 208 | NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil]; 209 | [JPEngine evaluateScript:script]; 210 | } 211 | ``` 212 | 213 | ```js 214 | include('test.js') //`include()`方法在扩展 JPInclude.m 里提供 215 | var view = require('UIView').alloc().init() 216 | 217 | //struct CGAffineTransform 类型在 JPCGTransform.m 里提供支持 218 | view.setTransform({a:1, b:0, c:0, d:1, tx:0, ty:100}) 219 | ``` 220 | 221 | 扩展可以在JS动态加载,更推荐这种加载方式,在需要用到时才加载: 222 | 223 | ```js 224 | require('JPEngine').addExtensions(['JPInclude', 'JPCGTransform']) 225 | 226 | // `include()` and `CGAffineTransform` is avaliable now. 227 | ``` 228 | 229 | 可以通过新增扩展为自己项目里的 struct 类型以及C函数添加支持,详情请见wiki页面:[Adding new extensions](https://github.com/bang590/JSPatch/wiki/Adding-new-extensions) 230 | 231 | 232 | ## 运行环境 233 | - iOS 7+ 234 | - JavaScriptCore.framework 235 | - 支持 armv7/armv7s/arm64 236 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 36A3014E652981DE469091F07DF75528 /* Pods-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 272643F56613CA0D336AE3DBF19DC404 /* Pods-dummy.m */; }; 11 | 6371AF01D6F66B6A45C901711DB2419F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */; }; 12 | 95B78BFC3D921957F8DD6A2CE3E0B499 /* JPEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = F42D53B779CDFD9110C64DDF1AFD75E2 /* JPEngine.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | A7B8ECCAD3285C571FFAE1F87156FBF2 /* JSPatch-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 646231915725112C4BB8AD5B621EF9A8 /* JSPatch-dummy.m */; }; 14 | B631FD187F97C2A9C17905FD653B9E7E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */; }; 15 | E90FE89EDA2F001944637A7C456AF004 /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = E4DC1CE286F8BD6A3EC4E1FAA1762707 /* JPEngine.m */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | C62CD4463F60706124CABB0C1921917E /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = FD1D53461DE538B7C8DFE0B76D857587; 24 | remoteInfo = JSPatch; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 0D62531571180EAB9B7917C2C6EEA578 /* JSPatch.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = JSPatch.xcconfig; sourceTree = ""; }; 30 | 10834806BD7B412BC24F347361FA2C8E /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-acknowledgements.plist"; sourceTree = ""; }; 31 | 272643F56613CA0D336AE3DBF19DC404 /* Pods-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-dummy.m"; sourceTree = ""; }; 32 | 36D847E95027FD5723ADCD8604128CB9 /* JSPatch-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "JSPatch-prefix.pch"; sourceTree = ""; }; 33 | 37DB56D75062CC75FCB0966E1C6E8A8E /* Pods-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-acknowledgements.markdown"; sourceTree = ""; }; 34 | 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 35 | 4E762F23EC34ED4A6FF3312D84E33A40 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.debug.xcconfig; sourceTree = ""; }; 36 | 646231915725112C4BB8AD5B621EF9A8 /* JSPatch-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "JSPatch-dummy.m"; sourceTree = ""; }; 37 | 66545465C8506C67921BEC4AC362A7FE /* libJSPatch.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libJSPatch.a; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 6911BECA35E7518D864239B7E898EEF3 /* Pods-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-frameworks.sh"; sourceTree = ""; }; 39 | 765D45DCD0A038CC3172A8CE7D000870 /* JSPatch.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = JSPatch.js; path = JSPatch/JSPatch.js; sourceTree = ""; }; 40 | 98C98CDFB3F20F2925F6CD1F141BB14F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.release.xcconfig; sourceTree = ""; }; 41 | A1A36D34413696BE466E2CA0AFF194DA /* Pods-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-resources.sh"; sourceTree = ""; }; 42 | BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 43 | D3B3F817B268251E3DBDB2F32D516377 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | E4DC1CE286F8BD6A3EC4E1FAA1762707 /* JPEngine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JPEngine.m; path = JSPatch/JPEngine.m; sourceTree = ""; }; 45 | F42D53B779CDFD9110C64DDF1AFD75E2 /* JPEngine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JPEngine.h; path = JSPatch/JPEngine.h; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 00CD0B0096519208337740D5BC28FE6D /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | 6371AF01D6F66B6A45C901711DB2419F /* Foundation.framework in Frameworks */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | 9D179D75ADF1F6C3069DD0EA94BF2F33 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | B631FD187F97C2A9C17905FD653B9E7E /* Foundation.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 037C0CA694176A3C0915F62C9D20B3E6 /* Targets Support Files */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | B3D1D13E0C6553800746CB8FD61CF946 /* Pods */, 72 | ); 73 | name = "Targets Support Files"; 74 | sourceTree = ""; 75 | }; 76 | 24C022379344A31B6AD4F1D00CEF2CFE /* Support Files */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 0D62531571180EAB9B7917C2C6EEA578 /* JSPatch.xcconfig */, 80 | 646231915725112C4BB8AD5B621EF9A8 /* JSPatch-dummy.m */, 81 | 36D847E95027FD5723ADCD8604128CB9 /* JSPatch-prefix.pch */, 82 | ); 83 | name = "Support Files"; 84 | path = "../Target Support Files/JSPatch"; 85 | sourceTree = ""; 86 | }; 87 | 3015A737A7ECC0EBD35FE7E52572BA1B /* Resources */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | ); 91 | name = Resources; 92 | sourceTree = ""; 93 | }; 94 | 38F50879C75E8B6C162E851C2713A4EE /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 66545465C8506C67921BEC4AC362A7FE /* libJSPatch.a */, 98 | D3B3F817B268251E3DBDB2F32D516377 /* libPods.a */, 99 | ); 100 | name = Products; 101 | sourceTree = ""; 102 | }; 103 | 44ECC580CFDD6131B078D1A4F89E0339 /* Resources */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 765D45DCD0A038CC3172A8CE7D000870 /* JSPatch.js */, 107 | ); 108 | name = Resources; 109 | sourceTree = ""; 110 | }; 111 | 4CC68880268D6361E20C4B11D4A75693 /* JSPatch */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 56F6CE720F9E5ED472AECFBAE5BAAA95 /* Core */, 115 | 44ECC580CFDD6131B078D1A4F89E0339 /* Resources */, 116 | 24C022379344A31B6AD4F1D00CEF2CFE /* Support Files */, 117 | ); 118 | path = JSPatch; 119 | sourceTree = ""; 120 | }; 121 | 56F6CE720F9E5ED472AECFBAE5BAAA95 /* Core */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | F42D53B779CDFD9110C64DDF1AFD75E2 /* JPEngine.h */, 125 | E4DC1CE286F8BD6A3EC4E1FAA1762707 /* JPEngine.m */, 126 | 3015A737A7ECC0EBD35FE7E52572BA1B /* Resources */, 127 | ); 128 | name = Core; 129 | sourceTree = ""; 130 | }; 131 | 7CBFE9E6C73CDD3CC3CBE068FBB7C976 /* Pods */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 4CC68880268D6361E20C4B11D4A75693 /* JSPatch */, 135 | ); 136 | name = Pods; 137 | sourceTree = ""; 138 | }; 139 | 7DB346D0F39D3F0E887471402A8071AB = { 140 | isa = PBXGroup; 141 | children = ( 142 | BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */, 143 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 144 | 7CBFE9E6C73CDD3CC3CBE068FBB7C976 /* Pods */, 145 | 38F50879C75E8B6C162E851C2713A4EE /* Products */, 146 | 037C0CA694176A3C0915F62C9D20B3E6 /* Targets Support Files */, 147 | ); 148 | sourceTree = ""; 149 | }; 150 | B3D1D13E0C6553800746CB8FD61CF946 /* Pods */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 37DB56D75062CC75FCB0966E1C6E8A8E /* Pods-acknowledgements.markdown */, 154 | 10834806BD7B412BC24F347361FA2C8E /* Pods-acknowledgements.plist */, 155 | 272643F56613CA0D336AE3DBF19DC404 /* Pods-dummy.m */, 156 | 6911BECA35E7518D864239B7E898EEF3 /* Pods-frameworks.sh */, 157 | A1A36D34413696BE466E2CA0AFF194DA /* Pods-resources.sh */, 158 | 4E762F23EC34ED4A6FF3312D84E33A40 /* Pods.debug.xcconfig */, 159 | 98C98CDFB3F20F2925F6CD1F141BB14F /* Pods.release.xcconfig */, 160 | ); 161 | name = Pods; 162 | path = "Target Support Files/Pods"; 163 | sourceTree = ""; 164 | }; 165 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | BF6342C8B29F4CEEA088EFF7AB4DE362 /* iOS */, 169 | ); 170 | name = Frameworks; 171 | sourceTree = ""; 172 | }; 173 | BF6342C8B29F4CEEA088EFF7AB4DE362 /* iOS */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */, 177 | ); 178 | name = iOS; 179 | sourceTree = ""; 180 | }; 181 | /* End PBXGroup section */ 182 | 183 | /* Begin PBXHeadersBuildPhase section */ 184 | EC0D5F87286AE5412CAC701D6ACAB402 /* Headers */ = { 185 | isa = PBXHeadersBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | 95B78BFC3D921957F8DD6A2CE3E0B499 /* JPEngine.h in Headers */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | /* End PBXHeadersBuildPhase section */ 193 | 194 | /* Begin PBXNativeTarget section */ 195 | 21A48DB9FD0DC3162F4466E6D11E704D /* Pods */ = { 196 | isa = PBXNativeTarget; 197 | buildConfigurationList = 33933B2D1F410B560046E08EE21C9262 /* Build configuration list for PBXNativeTarget "Pods" */; 198 | buildPhases = ( 199 | 54661FB7E0FBF7E908FA16D21D65F5A6 /* Sources */, 200 | 9D179D75ADF1F6C3069DD0EA94BF2F33 /* Frameworks */, 201 | ); 202 | buildRules = ( 203 | ); 204 | dependencies = ( 205 | D16EDE4DF82301AA4659AD38BE539D71 /* PBXTargetDependency */, 206 | ); 207 | name = Pods; 208 | productName = Pods; 209 | productReference = D3B3F817B268251E3DBDB2F32D516377 /* libPods.a */; 210 | productType = "com.apple.product-type.library.static"; 211 | }; 212 | FD1D53461DE538B7C8DFE0B76D857587 /* JSPatch */ = { 213 | isa = PBXNativeTarget; 214 | buildConfigurationList = D6237EEAE81FAC77DC4CDAA075B264E9 /* Build configuration list for PBXNativeTarget "JSPatch" */; 215 | buildPhases = ( 216 | 7F85DFA0BA8E5DF5155BF3912A24B2A0 /* Sources */, 217 | 00CD0B0096519208337740D5BC28FE6D /* Frameworks */, 218 | EC0D5F87286AE5412CAC701D6ACAB402 /* Headers */, 219 | ); 220 | buildRules = ( 221 | ); 222 | dependencies = ( 223 | ); 224 | name = JSPatch; 225 | productName = JSPatch; 226 | productReference = 66545465C8506C67921BEC4AC362A7FE /* libJSPatch.a */; 227 | productType = "com.apple.product-type.library.static"; 228 | }; 229 | /* End PBXNativeTarget section */ 230 | 231 | /* Begin PBXProject section */ 232 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 233 | isa = PBXProject; 234 | attributes = { 235 | LastSwiftUpdateCheck = 0700; 236 | LastUpgradeCheck = 0700; 237 | }; 238 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 239 | compatibilityVersion = "Xcode 3.2"; 240 | developmentRegion = English; 241 | hasScannedForEncodings = 0; 242 | knownRegions = ( 243 | en, 244 | ); 245 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 246 | productRefGroup = 38F50879C75E8B6C162E851C2713A4EE /* Products */; 247 | projectDirPath = ""; 248 | projectRoot = ""; 249 | targets = ( 250 | FD1D53461DE538B7C8DFE0B76D857587 /* JSPatch */, 251 | 21A48DB9FD0DC3162F4466E6D11E704D /* Pods */, 252 | ); 253 | }; 254 | /* End PBXProject section */ 255 | 256 | /* Begin PBXSourcesBuildPhase section */ 257 | 54661FB7E0FBF7E908FA16D21D65F5A6 /* Sources */ = { 258 | isa = PBXSourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | 36A3014E652981DE469091F07DF75528 /* Pods-dummy.m in Sources */, 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | }; 265 | 7F85DFA0BA8E5DF5155BF3912A24B2A0 /* Sources */ = { 266 | isa = PBXSourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | E90FE89EDA2F001944637A7C456AF004 /* JPEngine.m in Sources */, 270 | A7B8ECCAD3285C571FFAE1F87156FBF2 /* JSPatch-dummy.m in Sources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | /* End PBXSourcesBuildPhase section */ 275 | 276 | /* Begin PBXTargetDependency section */ 277 | D16EDE4DF82301AA4659AD38BE539D71 /* PBXTargetDependency */ = { 278 | isa = PBXTargetDependency; 279 | name = JSPatch; 280 | target = FD1D53461DE538B7C8DFE0B76D857587 /* JSPatch */; 281 | targetProxy = C62CD4463F60706124CABB0C1921917E /* PBXContainerItemProxy */; 282 | }; 283 | /* End PBXTargetDependency section */ 284 | 285 | /* Begin XCBuildConfiguration section */ 286 | 0889AAEC51323D0989CBFB0742D01F44 /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | baseConfigurationReference = 98C98CDFB3F20F2925F6CD1F141BB14F /* Pods.release.xcconfig */; 289 | buildSettings = { 290 | ENABLE_STRICT_OBJC_MSGSEND = YES; 291 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 292 | MACH_O_TYPE = staticlib; 293 | MTL_ENABLE_DEBUG_INFO = NO; 294 | OTHER_LDFLAGS = ""; 295 | OTHER_LIBTOOLFLAGS = ""; 296 | PODS_ROOT = "$(SRCROOT)"; 297 | PRODUCT_NAME = "$(TARGET_NAME)"; 298 | SDKROOT = iphoneos; 299 | SKIP_INSTALL = YES; 300 | }; 301 | name = Release; 302 | }; 303 | 5298DD0EA87F453DFA6C7E47FFBD58BB /* Debug */ = { 304 | isa = XCBuildConfiguration; 305 | baseConfigurationReference = 4E762F23EC34ED4A6FF3312D84E33A40 /* Pods.debug.xcconfig */; 306 | buildSettings = { 307 | ENABLE_STRICT_OBJC_MSGSEND = YES; 308 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 309 | MACH_O_TYPE = staticlib; 310 | MTL_ENABLE_DEBUG_INFO = YES; 311 | OTHER_LDFLAGS = ""; 312 | OTHER_LIBTOOLFLAGS = ""; 313 | PODS_ROOT = "$(SRCROOT)"; 314 | PRODUCT_NAME = "$(TARGET_NAME)"; 315 | SDKROOT = iphoneos; 316 | SKIP_INSTALL = YES; 317 | }; 318 | name = Debug; 319 | }; 320 | 61081AA978D5AC51EDE1A3E6675259CE /* Debug */ = { 321 | isa = XCBuildConfiguration; 322 | baseConfigurationReference = 0D62531571180EAB9B7917C2C6EEA578 /* JSPatch.xcconfig */; 323 | buildSettings = { 324 | ENABLE_STRICT_OBJC_MSGSEND = YES; 325 | GCC_PREFIX_HEADER = "Target Support Files/JSPatch/JSPatch-prefix.pch"; 326 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 327 | MTL_ENABLE_DEBUG_INFO = YES; 328 | OTHER_LDFLAGS = ""; 329 | OTHER_LIBTOOLFLAGS = ""; 330 | PRIVATE_HEADERS_FOLDER_PATH = ""; 331 | PRODUCT_NAME = "$(TARGET_NAME)"; 332 | PUBLIC_HEADERS_FOLDER_PATH = ""; 333 | SDKROOT = iphoneos; 334 | SKIP_INSTALL = YES; 335 | }; 336 | name = Debug; 337 | }; 338 | 6569F07DC21AD8B72752685013E3D9D8 /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ALWAYS_SEARCH_USER_PATHS = NO; 342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 343 | CLANG_CXX_LIBRARY = "libc++"; 344 | CLANG_ENABLE_MODULES = YES; 345 | CLANG_ENABLE_OBJC_ARC = YES; 346 | CLANG_WARN_BOOL_CONVERSION = YES; 347 | CLANG_WARN_CONSTANT_CONVERSION = YES; 348 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 349 | CLANG_WARN_EMPTY_BODY = YES; 350 | CLANG_WARN_ENUM_CONVERSION = YES; 351 | CLANG_WARN_INT_CONVERSION = YES; 352 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 353 | CLANG_WARN_UNREACHABLE_CODE = YES; 354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 355 | COPY_PHASE_STRIP = NO; 356 | GCC_C_LANGUAGE_STANDARD = gnu99; 357 | GCC_DYNAMIC_NO_PIC = NO; 358 | GCC_OPTIMIZATION_LEVEL = 0; 359 | GCC_PREPROCESSOR_DEFINITIONS = ( 360 | "DEBUG=1", 361 | "$(inherited)", 362 | ); 363 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 365 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 366 | GCC_WARN_UNDECLARED_SELECTOR = YES; 367 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 368 | GCC_WARN_UNUSED_FUNCTION = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 371 | ONLY_ACTIVE_ARCH = YES; 372 | STRIP_INSTALLED_PRODUCT = NO; 373 | SYMROOT = "${SRCROOT}/../build"; 374 | }; 375 | name = Debug; 376 | }; 377 | A14E2444F162A20E3776820E0ADFFB52 /* Release */ = { 378 | isa = XCBuildConfiguration; 379 | buildSettings = { 380 | ALWAYS_SEARCH_USER_PATHS = NO; 381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 382 | CLANG_CXX_LIBRARY = "libc++"; 383 | CLANG_ENABLE_MODULES = YES; 384 | CLANG_ENABLE_OBJC_ARC = YES; 385 | CLANG_WARN_BOOL_CONVERSION = YES; 386 | CLANG_WARN_CONSTANT_CONVERSION = YES; 387 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 388 | CLANG_WARN_EMPTY_BODY = YES; 389 | CLANG_WARN_ENUM_CONVERSION = YES; 390 | CLANG_WARN_INT_CONVERSION = YES; 391 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 392 | CLANG_WARN_UNREACHABLE_CODE = YES; 393 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 394 | COPY_PHASE_STRIP = YES; 395 | ENABLE_NS_ASSERTIONS = NO; 396 | GCC_C_LANGUAGE_STANDARD = gnu99; 397 | GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; 398 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 399 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 400 | GCC_WARN_UNDECLARED_SELECTOR = YES; 401 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 402 | GCC_WARN_UNUSED_FUNCTION = YES; 403 | GCC_WARN_UNUSED_VARIABLE = YES; 404 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 405 | STRIP_INSTALLED_PRODUCT = NO; 406 | SYMROOT = "${SRCROOT}/../build"; 407 | VALIDATE_PRODUCT = YES; 408 | }; 409 | name = Release; 410 | }; 411 | F520EC27BF7544CD45A039758C3B560C /* Release */ = { 412 | isa = XCBuildConfiguration; 413 | baseConfigurationReference = 0D62531571180EAB9B7917C2C6EEA578 /* JSPatch.xcconfig */; 414 | buildSettings = { 415 | ENABLE_STRICT_OBJC_MSGSEND = YES; 416 | GCC_PREFIX_HEADER = "Target Support Files/JSPatch/JSPatch-prefix.pch"; 417 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 418 | MTL_ENABLE_DEBUG_INFO = NO; 419 | OTHER_LDFLAGS = ""; 420 | OTHER_LIBTOOLFLAGS = ""; 421 | PRIVATE_HEADERS_FOLDER_PATH = ""; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | PUBLIC_HEADERS_FOLDER_PATH = ""; 424 | SDKROOT = iphoneos; 425 | SKIP_INSTALL = YES; 426 | }; 427 | name = Release; 428 | }; 429 | /* End XCBuildConfiguration section */ 430 | 431 | /* Begin XCConfigurationList section */ 432 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 433 | isa = XCConfigurationList; 434 | buildConfigurations = ( 435 | 6569F07DC21AD8B72752685013E3D9D8 /* Debug */, 436 | A14E2444F162A20E3776820E0ADFFB52 /* Release */, 437 | ); 438 | defaultConfigurationIsVisible = 0; 439 | defaultConfigurationName = Release; 440 | }; 441 | 33933B2D1F410B560046E08EE21C9262 /* Build configuration list for PBXNativeTarget "Pods" */ = { 442 | isa = XCConfigurationList; 443 | buildConfigurations = ( 444 | 5298DD0EA87F453DFA6C7E47FFBD58BB /* Debug */, 445 | 0889AAEC51323D0989CBFB0742D01F44 /* Release */, 446 | ); 447 | defaultConfigurationIsVisible = 0; 448 | defaultConfigurationName = Release; 449 | }; 450 | D6237EEAE81FAC77DC4CDAA075B264E9 /* Build configuration list for PBXNativeTarget "JSPatch" */ = { 451 | isa = XCConfigurationList; 452 | buildConfigurations = ( 453 | 61081AA978D5AC51EDE1A3E6675259CE /* Debug */, 454 | F520EC27BF7544CD45A039758C3B560C /* Release */, 455 | ); 456 | defaultConfigurationIsVisible = 0; 457 | defaultConfigurationName = Release; 458 | }; 459 | /* End XCConfigurationList section */ 460 | }; 461 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 462 | } 463 | -------------------------------------------------------------------------------- /JsPatchDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 70E3100954E85E928859C3CC /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AC185FF1C53185103E53C399 /* libPods.a */; }; 11 | BFA5718C1C1C2D170044AAB4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BFA5718B1C1C2D170044AAB4 /* main.m */; }; 12 | BFA5718F1C1C2D170044AAB4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BFA5718E1C1C2D170044AAB4 /* AppDelegate.m */; }; 13 | BFA571921C1C2D170044AAB4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BFA571911C1C2D170044AAB4 /* ViewController.m */; }; 14 | BFA571951C1C2D170044AAB4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFA571931C1C2D170044AAB4 /* Main.storyboard */; }; 15 | BFA571971C1C2D170044AAB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFA571961C1C2D170044AAB4 /* Assets.xcassets */; }; 16 | BFA5719A1C1C2D170044AAB4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFA571981C1C2D170044AAB4 /* LaunchScreen.storyboard */; }; 17 | BFA571A51C1C2D170044AAB4 /* JsPatchDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BFA571A41C1C2D170044AAB4 /* JsPatchDemoTests.m */; }; 18 | BFA571B01C1C2D170044AAB4 /* JsPatchDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = BFA571AF1C1C2D170044AAB4 /* JsPatchDemoUITests.m */; }; 19 | BFA571BF1C1C2F320044AAB4 /* mq.js in Resources */ = {isa = PBXBuildFile; fileRef = BFA571BE1C1C2F320044AAB4 /* mq.js */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | BFA571A11C1C2D170044AAB4 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = BFA5717F1C1C2D170044AAB4 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = BFA571861C1C2D170044AAB4; 28 | remoteInfo = JsPatchDemo; 29 | }; 30 | BFA571AC1C1C2D170044AAB4 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = BFA5717F1C1C2D170044AAB4 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = BFA571861C1C2D170044AAB4; 35 | remoteInfo = JsPatchDemo; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 09FAD90697E5864D2D23E1DA /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 41 | AC185FF1C53185103E53C399 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | BFA571871C1C2D170044AAB4 /* JsPatchDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JsPatchDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | BFA5718B1C1C2D170044AAB4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 44 | BFA5718D1C1C2D170044AAB4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | BFA5718E1C1C2D170044AAB4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | BFA571901C1C2D170044AAB4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 47 | BFA571911C1C2D170044AAB4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 48 | BFA571941C1C2D170044AAB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | BFA571961C1C2D170044AAB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | BFA571991C1C2D170044AAB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 51 | BFA5719B1C1C2D170044AAB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | BFA571A01C1C2D170044AAB4 /* JsPatchDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JsPatchDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | BFA571A41C1C2D170044AAB4 /* JsPatchDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JsPatchDemoTests.m; sourceTree = ""; }; 54 | BFA571A61C1C2D170044AAB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | BFA571AB1C1C2D170044AAB4 /* JsPatchDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JsPatchDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | BFA571AF1C1C2D170044AAB4 /* JsPatchDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JsPatchDemoUITests.m; sourceTree = ""; }; 57 | BFA571B11C1C2D170044AAB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | BFA571BE1C1C2F320044AAB4 /* mq.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = mq.js; sourceTree = ""; }; 59 | F86241FF06A9BB88B444575A /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | BFA571841C1C2D170044AAB4 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 70E3100954E85E928859C3CC /* libPods.a in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | BFA5719D1C1C2D170044AAB4 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | BFA571A81C1C2D170044AAB4 /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXFrameworksBuildPhase section */ 86 | 87 | /* Begin PBXGroup section */ 88 | 366E4A746CA2C90AE1848964 /* Pods */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 09FAD90697E5864D2D23E1DA /* Pods.debug.xcconfig */, 92 | F86241FF06A9BB88B444575A /* Pods.release.xcconfig */, 93 | ); 94 | name = Pods; 95 | sourceTree = ""; 96 | }; 97 | BFA5717E1C1C2D170044AAB4 = { 98 | isa = PBXGroup; 99 | children = ( 100 | BFA571891C1C2D170044AAB4 /* JsPatchDemo */, 101 | BFA571A31C1C2D170044AAB4 /* JsPatchDemoTests */, 102 | BFA571AE1C1C2D170044AAB4 /* JsPatchDemoUITests */, 103 | BFA571881C1C2D170044AAB4 /* Products */, 104 | 366E4A746CA2C90AE1848964 /* Pods */, 105 | EFA86F963B3FBD90AE828A6D /* Frameworks */, 106 | ); 107 | sourceTree = ""; 108 | }; 109 | BFA571881C1C2D170044AAB4 /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | BFA571871C1C2D170044AAB4 /* JsPatchDemo.app */, 113 | BFA571A01C1C2D170044AAB4 /* JsPatchDemoTests.xctest */, 114 | BFA571AB1C1C2D170044AAB4 /* JsPatchDemoUITests.xctest */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | BFA571891C1C2D170044AAB4 /* JsPatchDemo */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | BFA571BD1C1C2F250044AAB4 /* JS */, 123 | BFA5718D1C1C2D170044AAB4 /* AppDelegate.h */, 124 | BFA5718E1C1C2D170044AAB4 /* AppDelegate.m */, 125 | BFA571901C1C2D170044AAB4 /* ViewController.h */, 126 | BFA571911C1C2D170044AAB4 /* ViewController.m */, 127 | BFA571931C1C2D170044AAB4 /* Main.storyboard */, 128 | BFA571961C1C2D170044AAB4 /* Assets.xcassets */, 129 | BFA571981C1C2D170044AAB4 /* LaunchScreen.storyboard */, 130 | BFA5719B1C1C2D170044AAB4 /* Info.plist */, 131 | BFA5718A1C1C2D170044AAB4 /* Supporting Files */, 132 | ); 133 | path = JsPatchDemo; 134 | sourceTree = ""; 135 | }; 136 | BFA5718A1C1C2D170044AAB4 /* Supporting Files */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | BFA5718B1C1C2D170044AAB4 /* main.m */, 140 | ); 141 | name = "Supporting Files"; 142 | sourceTree = ""; 143 | }; 144 | BFA571A31C1C2D170044AAB4 /* JsPatchDemoTests */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | BFA571A41C1C2D170044AAB4 /* JsPatchDemoTests.m */, 148 | BFA571A61C1C2D170044AAB4 /* Info.plist */, 149 | ); 150 | path = JsPatchDemoTests; 151 | sourceTree = ""; 152 | }; 153 | BFA571AE1C1C2D170044AAB4 /* JsPatchDemoUITests */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | BFA571AF1C1C2D170044AAB4 /* JsPatchDemoUITests.m */, 157 | BFA571B11C1C2D170044AAB4 /* Info.plist */, 158 | ); 159 | path = JsPatchDemoUITests; 160 | sourceTree = ""; 161 | }; 162 | BFA571BD1C1C2F250044AAB4 /* JS */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | BFA571BE1C1C2F320044AAB4 /* mq.js */, 166 | ); 167 | name = JS; 168 | sourceTree = ""; 169 | }; 170 | EFA86F963B3FBD90AE828A6D /* Frameworks */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | AC185FF1C53185103E53C399 /* libPods.a */, 174 | ); 175 | name = Frameworks; 176 | sourceTree = ""; 177 | }; 178 | /* End PBXGroup section */ 179 | 180 | /* Begin PBXNativeTarget section */ 181 | BFA571861C1C2D170044AAB4 /* JsPatchDemo */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = BFA571B41C1C2D170044AAB4 /* Build configuration list for PBXNativeTarget "JsPatchDemo" */; 184 | buildPhases = ( 185 | 7AF371528AE7A206F508511E /* Check Pods Manifest.lock */, 186 | BFA571831C1C2D170044AAB4 /* Sources */, 187 | BFA571841C1C2D170044AAB4 /* Frameworks */, 188 | BFA571851C1C2D170044AAB4 /* Resources */, 189 | F487541358326C03C39491B0 /* Embed Pods Frameworks */, 190 | A0FB69C7C18C329E0B131155 /* Copy Pods Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | ); 196 | name = JsPatchDemo; 197 | productName = JsPatchDemo; 198 | productReference = BFA571871C1C2D170044AAB4 /* JsPatchDemo.app */; 199 | productType = "com.apple.product-type.application"; 200 | }; 201 | BFA5719F1C1C2D170044AAB4 /* JsPatchDemoTests */ = { 202 | isa = PBXNativeTarget; 203 | buildConfigurationList = BFA571B71C1C2D170044AAB4 /* Build configuration list for PBXNativeTarget "JsPatchDemoTests" */; 204 | buildPhases = ( 205 | BFA5719C1C1C2D170044AAB4 /* Sources */, 206 | BFA5719D1C1C2D170044AAB4 /* Frameworks */, 207 | BFA5719E1C1C2D170044AAB4 /* Resources */, 208 | ); 209 | buildRules = ( 210 | ); 211 | dependencies = ( 212 | BFA571A21C1C2D170044AAB4 /* PBXTargetDependency */, 213 | ); 214 | name = JsPatchDemoTests; 215 | productName = JsPatchDemoTests; 216 | productReference = BFA571A01C1C2D170044AAB4 /* JsPatchDemoTests.xctest */; 217 | productType = "com.apple.product-type.bundle.unit-test"; 218 | }; 219 | BFA571AA1C1C2D170044AAB4 /* JsPatchDemoUITests */ = { 220 | isa = PBXNativeTarget; 221 | buildConfigurationList = BFA571BA1C1C2D170044AAB4 /* Build configuration list for PBXNativeTarget "JsPatchDemoUITests" */; 222 | buildPhases = ( 223 | BFA571A71C1C2D170044AAB4 /* Sources */, 224 | BFA571A81C1C2D170044AAB4 /* Frameworks */, 225 | BFA571A91C1C2D170044AAB4 /* Resources */, 226 | ); 227 | buildRules = ( 228 | ); 229 | dependencies = ( 230 | BFA571AD1C1C2D170044AAB4 /* PBXTargetDependency */, 231 | ); 232 | name = JsPatchDemoUITests; 233 | productName = JsPatchDemoUITests; 234 | productReference = BFA571AB1C1C2D170044AAB4 /* JsPatchDemoUITests.xctest */; 235 | productType = "com.apple.product-type.bundle.ui-testing"; 236 | }; 237 | /* End PBXNativeTarget section */ 238 | 239 | /* Begin PBXProject section */ 240 | BFA5717F1C1C2D170044AAB4 /* Project object */ = { 241 | isa = PBXProject; 242 | attributes = { 243 | LastUpgradeCheck = 0710; 244 | ORGANIZATIONNAME = meiqing; 245 | TargetAttributes = { 246 | BFA571861C1C2D170044AAB4 = { 247 | CreatedOnToolsVersion = 7.1.1; 248 | }; 249 | BFA5719F1C1C2D170044AAB4 = { 250 | CreatedOnToolsVersion = 7.1.1; 251 | TestTargetID = BFA571861C1C2D170044AAB4; 252 | }; 253 | BFA571AA1C1C2D170044AAB4 = { 254 | CreatedOnToolsVersion = 7.1.1; 255 | TestTargetID = BFA571861C1C2D170044AAB4; 256 | }; 257 | }; 258 | }; 259 | buildConfigurationList = BFA571821C1C2D170044AAB4 /* Build configuration list for PBXProject "JsPatchDemo" */; 260 | compatibilityVersion = "Xcode 3.2"; 261 | developmentRegion = English; 262 | hasScannedForEncodings = 0; 263 | knownRegions = ( 264 | en, 265 | Base, 266 | ); 267 | mainGroup = BFA5717E1C1C2D170044AAB4; 268 | productRefGroup = BFA571881C1C2D170044AAB4 /* Products */; 269 | projectDirPath = ""; 270 | projectRoot = ""; 271 | targets = ( 272 | BFA571861C1C2D170044AAB4 /* JsPatchDemo */, 273 | BFA5719F1C1C2D170044AAB4 /* JsPatchDemoTests */, 274 | BFA571AA1C1C2D170044AAB4 /* JsPatchDemoUITests */, 275 | ); 276 | }; 277 | /* End PBXProject section */ 278 | 279 | /* Begin PBXResourcesBuildPhase section */ 280 | BFA571851C1C2D170044AAB4 /* Resources */ = { 281 | isa = PBXResourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | BFA5719A1C1C2D170044AAB4 /* LaunchScreen.storyboard in Resources */, 285 | BFA571971C1C2D170044AAB4 /* Assets.xcassets in Resources */, 286 | BFA571BF1C1C2F320044AAB4 /* mq.js in Resources */, 287 | BFA571951C1C2D170044AAB4 /* Main.storyboard in Resources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | BFA5719E1C1C2D170044AAB4 /* Resources */ = { 292 | isa = PBXResourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | BFA571A91C1C2D170044AAB4 /* Resources */ = { 299 | isa = PBXResourcesBuildPhase; 300 | buildActionMask = 2147483647; 301 | files = ( 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | /* End PBXResourcesBuildPhase section */ 306 | 307 | /* Begin PBXShellScriptBuildPhase section */ 308 | 7AF371528AE7A206F508511E /* Check Pods Manifest.lock */ = { 309 | isa = PBXShellScriptBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | ); 313 | inputPaths = ( 314 | ); 315 | name = "Check Pods Manifest.lock"; 316 | outputPaths = ( 317 | ); 318 | runOnlyForDeploymentPostprocessing = 0; 319 | shellPath = /bin/sh; 320 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 321 | showEnvVarsInLog = 0; 322 | }; 323 | A0FB69C7C18C329E0B131155 /* Copy Pods Resources */ = { 324 | isa = PBXShellScriptBuildPhase; 325 | buildActionMask = 2147483647; 326 | files = ( 327 | ); 328 | inputPaths = ( 329 | ); 330 | name = "Copy Pods Resources"; 331 | outputPaths = ( 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | shellPath = /bin/sh; 335 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 336 | showEnvVarsInLog = 0; 337 | }; 338 | F487541358326C03C39491B0 /* Embed Pods Frameworks */ = { 339 | isa = PBXShellScriptBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | ); 343 | inputPaths = ( 344 | ); 345 | name = "Embed Pods Frameworks"; 346 | outputPaths = ( 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | shellPath = /bin/sh; 350 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; 351 | showEnvVarsInLog = 0; 352 | }; 353 | /* End PBXShellScriptBuildPhase section */ 354 | 355 | /* Begin PBXSourcesBuildPhase section */ 356 | BFA571831C1C2D170044AAB4 /* Sources */ = { 357 | isa = PBXSourcesBuildPhase; 358 | buildActionMask = 2147483647; 359 | files = ( 360 | BFA571921C1C2D170044AAB4 /* ViewController.m in Sources */, 361 | BFA5718F1C1C2D170044AAB4 /* AppDelegate.m in Sources */, 362 | BFA5718C1C1C2D170044AAB4 /* main.m in Sources */, 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | }; 366 | BFA5719C1C1C2D170044AAB4 /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | BFA571A51C1C2D170044AAB4 /* JsPatchDemoTests.m in Sources */, 371 | ); 372 | runOnlyForDeploymentPostprocessing = 0; 373 | }; 374 | BFA571A71C1C2D170044AAB4 /* Sources */ = { 375 | isa = PBXSourcesBuildPhase; 376 | buildActionMask = 2147483647; 377 | files = ( 378 | BFA571B01C1C2D170044AAB4 /* JsPatchDemoUITests.m in Sources */, 379 | ); 380 | runOnlyForDeploymentPostprocessing = 0; 381 | }; 382 | /* End PBXSourcesBuildPhase section */ 383 | 384 | /* Begin PBXTargetDependency section */ 385 | BFA571A21C1C2D170044AAB4 /* PBXTargetDependency */ = { 386 | isa = PBXTargetDependency; 387 | target = BFA571861C1C2D170044AAB4 /* JsPatchDemo */; 388 | targetProxy = BFA571A11C1C2D170044AAB4 /* PBXContainerItemProxy */; 389 | }; 390 | BFA571AD1C1C2D170044AAB4 /* PBXTargetDependency */ = { 391 | isa = PBXTargetDependency; 392 | target = BFA571861C1C2D170044AAB4 /* JsPatchDemo */; 393 | targetProxy = BFA571AC1C1C2D170044AAB4 /* PBXContainerItemProxy */; 394 | }; 395 | /* End PBXTargetDependency section */ 396 | 397 | /* Begin PBXVariantGroup section */ 398 | BFA571931C1C2D170044AAB4 /* Main.storyboard */ = { 399 | isa = PBXVariantGroup; 400 | children = ( 401 | BFA571941C1C2D170044AAB4 /* Base */, 402 | ); 403 | name = Main.storyboard; 404 | sourceTree = ""; 405 | }; 406 | BFA571981C1C2D170044AAB4 /* LaunchScreen.storyboard */ = { 407 | isa = PBXVariantGroup; 408 | children = ( 409 | BFA571991C1C2D170044AAB4 /* Base */, 410 | ); 411 | name = LaunchScreen.storyboard; 412 | sourceTree = ""; 413 | }; 414 | /* End PBXVariantGroup section */ 415 | 416 | /* Begin XCBuildConfiguration section */ 417 | BFA571B21C1C2D170044AAB4 /* Debug */ = { 418 | isa = XCBuildConfiguration; 419 | buildSettings = { 420 | ALWAYS_SEARCH_USER_PATHS = NO; 421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 422 | CLANG_CXX_LIBRARY = "libc++"; 423 | CLANG_ENABLE_MODULES = YES; 424 | CLANG_ENABLE_OBJC_ARC = YES; 425 | CLANG_WARN_BOOL_CONVERSION = YES; 426 | CLANG_WARN_CONSTANT_CONVERSION = YES; 427 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 428 | CLANG_WARN_EMPTY_BODY = YES; 429 | CLANG_WARN_ENUM_CONVERSION = YES; 430 | CLANG_WARN_INT_CONVERSION = YES; 431 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 432 | CLANG_WARN_UNREACHABLE_CODE = YES; 433 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 434 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 435 | COPY_PHASE_STRIP = NO; 436 | DEBUG_INFORMATION_FORMAT = dwarf; 437 | ENABLE_STRICT_OBJC_MSGSEND = YES; 438 | ENABLE_TESTABILITY = YES; 439 | GCC_C_LANGUAGE_STANDARD = gnu99; 440 | GCC_DYNAMIC_NO_PIC = NO; 441 | GCC_NO_COMMON_BLOCKS = YES; 442 | GCC_OPTIMIZATION_LEVEL = 0; 443 | GCC_PREPROCESSOR_DEFINITIONS = ( 444 | "DEBUG=1", 445 | "$(inherited)", 446 | ); 447 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 448 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 449 | GCC_WARN_UNDECLARED_SELECTOR = YES; 450 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 451 | GCC_WARN_UNUSED_FUNCTION = YES; 452 | GCC_WARN_UNUSED_VARIABLE = YES; 453 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 454 | MTL_ENABLE_DEBUG_INFO = YES; 455 | ONLY_ACTIVE_ARCH = YES; 456 | SDKROOT = iphoneos; 457 | TARGETED_DEVICE_FAMILY = "1,2"; 458 | }; 459 | name = Debug; 460 | }; 461 | BFA571B31C1C2D170044AAB4 /* Release */ = { 462 | isa = XCBuildConfiguration; 463 | buildSettings = { 464 | ALWAYS_SEARCH_USER_PATHS = NO; 465 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 466 | CLANG_CXX_LIBRARY = "libc++"; 467 | CLANG_ENABLE_MODULES = YES; 468 | CLANG_ENABLE_OBJC_ARC = YES; 469 | CLANG_WARN_BOOL_CONVERSION = YES; 470 | CLANG_WARN_CONSTANT_CONVERSION = YES; 471 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 472 | CLANG_WARN_EMPTY_BODY = YES; 473 | CLANG_WARN_ENUM_CONVERSION = YES; 474 | CLANG_WARN_INT_CONVERSION = YES; 475 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 476 | CLANG_WARN_UNREACHABLE_CODE = YES; 477 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 478 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 479 | COPY_PHASE_STRIP = NO; 480 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 481 | ENABLE_NS_ASSERTIONS = NO; 482 | ENABLE_STRICT_OBJC_MSGSEND = YES; 483 | GCC_C_LANGUAGE_STANDARD = gnu99; 484 | GCC_NO_COMMON_BLOCKS = YES; 485 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 486 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 487 | GCC_WARN_UNDECLARED_SELECTOR = YES; 488 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 489 | GCC_WARN_UNUSED_FUNCTION = YES; 490 | GCC_WARN_UNUSED_VARIABLE = YES; 491 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 492 | MTL_ENABLE_DEBUG_INFO = NO; 493 | SDKROOT = iphoneos; 494 | TARGETED_DEVICE_FAMILY = "1,2"; 495 | VALIDATE_PRODUCT = YES; 496 | }; 497 | name = Release; 498 | }; 499 | BFA571B51C1C2D170044AAB4 /* Debug */ = { 500 | isa = XCBuildConfiguration; 501 | baseConfigurationReference = 09FAD90697E5864D2D23E1DA /* Pods.debug.xcconfig */; 502 | buildSettings = { 503 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 504 | INFOPLIST_FILE = JsPatchDemo/Info.plist; 505 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 506 | PRODUCT_BUNDLE_IDENTIFIER = com.meiqing.JsPatchDemo; 507 | PRODUCT_NAME = "$(TARGET_NAME)"; 508 | }; 509 | name = Debug; 510 | }; 511 | BFA571B61C1C2D170044AAB4 /* Release */ = { 512 | isa = XCBuildConfiguration; 513 | baseConfigurationReference = F86241FF06A9BB88B444575A /* Pods.release.xcconfig */; 514 | buildSettings = { 515 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 516 | INFOPLIST_FILE = JsPatchDemo/Info.plist; 517 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 518 | PRODUCT_BUNDLE_IDENTIFIER = com.meiqing.JsPatchDemo; 519 | PRODUCT_NAME = "$(TARGET_NAME)"; 520 | }; 521 | name = Release; 522 | }; 523 | BFA571B81C1C2D170044AAB4 /* Debug */ = { 524 | isa = XCBuildConfiguration; 525 | buildSettings = { 526 | BUNDLE_LOADER = "$(TEST_HOST)"; 527 | INFOPLIST_FILE = JsPatchDemoTests/Info.plist; 528 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 529 | PRODUCT_BUNDLE_IDENTIFIER = com.meiqing.JsPatchDemoTests; 530 | PRODUCT_NAME = "$(TARGET_NAME)"; 531 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JsPatchDemo.app/JsPatchDemo"; 532 | }; 533 | name = Debug; 534 | }; 535 | BFA571B91C1C2D170044AAB4 /* Release */ = { 536 | isa = XCBuildConfiguration; 537 | buildSettings = { 538 | BUNDLE_LOADER = "$(TEST_HOST)"; 539 | INFOPLIST_FILE = JsPatchDemoTests/Info.plist; 540 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 541 | PRODUCT_BUNDLE_IDENTIFIER = com.meiqing.JsPatchDemoTests; 542 | PRODUCT_NAME = "$(TARGET_NAME)"; 543 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JsPatchDemo.app/JsPatchDemo"; 544 | }; 545 | name = Release; 546 | }; 547 | BFA571BB1C1C2D170044AAB4 /* Debug */ = { 548 | isa = XCBuildConfiguration; 549 | buildSettings = { 550 | INFOPLIST_FILE = JsPatchDemoUITests/Info.plist; 551 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 552 | PRODUCT_BUNDLE_IDENTIFIER = com.meiqing.JsPatchDemoUITests; 553 | PRODUCT_NAME = "$(TARGET_NAME)"; 554 | TEST_TARGET_NAME = JsPatchDemo; 555 | USES_XCTRUNNER = YES; 556 | }; 557 | name = Debug; 558 | }; 559 | BFA571BC1C1C2D170044AAB4 /* Release */ = { 560 | isa = XCBuildConfiguration; 561 | buildSettings = { 562 | INFOPLIST_FILE = JsPatchDemoUITests/Info.plist; 563 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 564 | PRODUCT_BUNDLE_IDENTIFIER = com.meiqing.JsPatchDemoUITests; 565 | PRODUCT_NAME = "$(TARGET_NAME)"; 566 | TEST_TARGET_NAME = JsPatchDemo; 567 | USES_XCTRUNNER = YES; 568 | }; 569 | name = Release; 570 | }; 571 | /* End XCBuildConfiguration section */ 572 | 573 | /* Begin XCConfigurationList section */ 574 | BFA571821C1C2D170044AAB4 /* Build configuration list for PBXProject "JsPatchDemo" */ = { 575 | isa = XCConfigurationList; 576 | buildConfigurations = ( 577 | BFA571B21C1C2D170044AAB4 /* Debug */, 578 | BFA571B31C1C2D170044AAB4 /* Release */, 579 | ); 580 | defaultConfigurationIsVisible = 0; 581 | defaultConfigurationName = Release; 582 | }; 583 | BFA571B41C1C2D170044AAB4 /* Build configuration list for PBXNativeTarget "JsPatchDemo" */ = { 584 | isa = XCConfigurationList; 585 | buildConfigurations = ( 586 | BFA571B51C1C2D170044AAB4 /* Debug */, 587 | BFA571B61C1C2D170044AAB4 /* Release */, 588 | ); 589 | defaultConfigurationIsVisible = 0; 590 | defaultConfigurationName = Release; 591 | }; 592 | BFA571B71C1C2D170044AAB4 /* Build configuration list for PBXNativeTarget "JsPatchDemoTests" */ = { 593 | isa = XCConfigurationList; 594 | buildConfigurations = ( 595 | BFA571B81C1C2D170044AAB4 /* Debug */, 596 | BFA571B91C1C2D170044AAB4 /* Release */, 597 | ); 598 | defaultConfigurationIsVisible = 0; 599 | defaultConfigurationName = Release; 600 | }; 601 | BFA571BA1C1C2D170044AAB4 /* Build configuration list for PBXNativeTarget "JsPatchDemoUITests" */ = { 602 | isa = XCConfigurationList; 603 | buildConfigurations = ( 604 | BFA571BB1C1C2D170044AAB4 /* Debug */, 605 | BFA571BC1C1C2D170044AAB4 /* Release */, 606 | ); 607 | defaultConfigurationIsVisible = 0; 608 | defaultConfigurationName = Release; 609 | }; 610 | /* End XCConfigurationList section */ 611 | }; 612 | rootObject = BFA5717F1C1C2D170044AAB4 /* Project object */; 613 | } 614 | -------------------------------------------------------------------------------- /Pods/JSPatch/JSPatch/JPEngine.m: -------------------------------------------------------------------------------- 1 | // JPEngine.m 2 | // JSPatch 3 | // 4 | // Created by bang on 15/4/30. 5 | // Copyright (c) 2015 bang. All rights reserved. 6 | // 7 | 8 | #import "JPEngine.h" 9 | #import 10 | #import 11 | #import 12 | 13 | @interface JPBoxing : NSObject 14 | @property (nonatomic) id obj; 15 | @property (nonatomic) void *pointer; 16 | @property (nonatomic) Class cls; 17 | @property (nonatomic, weak) id weakObj; 18 | - (id)unbox; 19 | - (void *)unboxPointer; 20 | - (Class)unboxClass; 21 | @end 22 | 23 | @implementation JPBoxing 24 | 25 | #define JPBOXING_GEN(_name, _prop, _type) \ 26 | + (instancetype)_name:(_type)obj \ 27 | { \ 28 | JPBoxing *boxing = [[JPBoxing alloc] init]; \ 29 | boxing._prop = obj; \ 30 | return boxing; \ 31 | } 32 | 33 | JPBOXING_GEN(boxObj, obj, id) 34 | JPBOXING_GEN(boxPointer, pointer, void *) 35 | JPBOXING_GEN(boxClass, cls, Class) 36 | JPBOXING_GEN(boxWeakObj, weakObj, id) 37 | 38 | - (id)unbox 39 | { 40 | if (self.obj) return self.obj; 41 | if (self.weakObj) return self.weakObj; 42 | return self; 43 | } 44 | - (void *)unboxPointer 45 | { 46 | return self.pointer; 47 | } 48 | - (Class)unboxClass 49 | { 50 | return self.cls; 51 | } 52 | @end 53 | 54 | 55 | 56 | @implementation JPEngine 57 | 58 | static JSContext *_context; 59 | static NSString *_regexStr = @"(?" intoString:&protocolNames]; 324 | } 325 | } 326 | NSArray *protocols = [protocolNames componentsSeparatedByString:@","]; 327 | if (!superClassName) superClassName = @"NSObject"; 328 | className = trim(className); 329 | superClassName = trim(superClassName); 330 | 331 | Class cls = NSClassFromString(className); 332 | if (!cls) { 333 | Class superCls = NSClassFromString(superClassName); 334 | cls = objc_allocateClassPair(superCls, className.UTF8String, 0); 335 | objc_registerClassPair(cls); 336 | } 337 | 338 | for (int i = 0; i < 2; i ++) { 339 | BOOL isInstance = i == 0; 340 | JSValue *jsMethods = isInstance ? instanceMethods: classMethods; 341 | 342 | Class currCls = isInstance ? cls: objc_getMetaClass(className.UTF8String); 343 | NSDictionary *methodDict = [jsMethods toDictionary]; 344 | for (NSString *jsMethodName in methodDict.allKeys) { 345 | JSValue *jsMethodArr = [jsMethods valueForProperty:jsMethodName]; 346 | int numberOfArg = [jsMethodArr[0] toInt32]; 347 | NSString *tmpJSMethodName = [jsMethodName stringByReplacingOccurrencesOfString:@"__" withString:@"-"]; 348 | NSString *selectorName = [tmpJSMethodName stringByReplacingOccurrencesOfString:@"_" withString:@":"]; 349 | selectorName = [selectorName stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; 350 | 351 | if (!countArgRegex) { 352 | countArgRegex = [NSRegularExpression regularExpressionWithPattern:@":" options:NSRegularExpressionCaseInsensitive error:nil]; 353 | } 354 | NSUInteger numberOfMatches = [countArgRegex numberOfMatchesInString:selectorName options:0 range:NSMakeRange(0, [selectorName length])]; 355 | if (numberOfMatches < numberOfArg) { 356 | selectorName = [selectorName stringByAppendingString:@":"]; 357 | } 358 | 359 | JSValue *jsMethod = jsMethodArr[1]; 360 | if (class_respondsToSelector(currCls, NSSelectorFromString(selectorName))) { 361 | overrideMethod(currCls, selectorName, jsMethod, !isInstance, NULL); 362 | } else { 363 | BOOL overrided = NO; 364 | for (NSString *protocolName in protocols) { 365 | char *types = methodTypesInProtocol(protocolName, selectorName, isInstance, YES); 366 | if (!types) types = methodTypesInProtocol(protocolName, selectorName, isInstance, NO); 367 | if (types) { 368 | overrideMethod(currCls, selectorName, jsMethod, !isInstance, types); 369 | free(types); 370 | overrided = YES; 371 | break; 372 | } 373 | } 374 | if (!overrided) { 375 | NSMutableString *typeDescStr = [@"@@:" mutableCopy]; 376 | for (int i = 0; i < numberOfArg; i ++) { 377 | [typeDescStr appendString:@"@"]; 378 | } 379 | overrideMethod(currCls, selectorName, jsMethod, !isInstance, [typeDescStr cStringUsingEncoding:NSUTF8StringEncoding]); 380 | } 381 | } 382 | } 383 | } 384 | 385 | #pragma clang diagnostic push 386 | #pragma clang diagnostic ignored "-Wundeclared-selector" 387 | class_addMethod(cls, @selector(getProp:), (IMP)getPropIMP, "@@:@"); 388 | class_addMethod(cls, @selector(setProp:forKey:), (IMP)setPropIMP, "v@:@@"); 389 | #pragma clang diagnostic pop 390 | 391 | return @{@"cls": className}; 392 | } 393 | 394 | static JSValue* getJSFunctionInObjectHierachy(id slf, NSString *selectorName) 395 | { 396 | Class cls = object_getClass(slf); 397 | JSValue *func = _JSOverideMethods[cls][selectorName]; 398 | while (!func) { 399 | cls = class_getSuperclass(cls); 400 | if (!cls) { 401 | NSCAssert(NO, @"warning can not find selector %@", selectorName); 402 | return nil; 403 | } 404 | func = _JSOverideMethods[cls][selectorName]; 405 | } 406 | return func; 407 | } 408 | 409 | #pragma clang diagnostic pop 410 | 411 | static void JPForwardInvocation(id slf, SEL selector, NSInvocation *invocation) 412 | { 413 | NSMethodSignature *methodSignature = [invocation methodSignature]; 414 | NSInteger numberOfArguments = [methodSignature numberOfArguments]; 415 | 416 | NSString *selectorName = NSStringFromSelector(invocation.selector); 417 | NSString *JPSelectorName = [NSString stringWithFormat:@"_JP%@", selectorName]; 418 | SEL JPSelector = NSSelectorFromString(JPSelectorName); 419 | 420 | if (!class_respondsToSelector(object_getClass(slf), JPSelector)) { 421 | #pragma clang diagnostic push 422 | #pragma clang diagnostic ignored "-Wundeclared-selector" 423 | SEL origForwardSelector = @selector(ORIGforwardInvocation:); 424 | NSMethodSignature *methodSignature = [slf methodSignatureForSelector:origForwardSelector]; 425 | if (!methodSignature) { 426 | NSCAssert(methodSignature, @"unrecognized selector -ORIGforwardInvocation: for instance %@", slf); 427 | return; 428 | } 429 | NSInvocation *forwardInv= [NSInvocation invocationWithMethodSignature:methodSignature]; 430 | [forwardInv setTarget:slf]; 431 | [forwardInv setSelector:origForwardSelector]; 432 | [forwardInv setArgument:&invocation atIndex:2]; 433 | [forwardInv invoke]; 434 | return; 435 | #pragma clang diagnostic pop 436 | } 437 | 438 | NSMutableArray *argList = [[NSMutableArray alloc] init]; 439 | if ([slf class] == slf) { 440 | [argList addObject:[JSValue valueWithObject:@{@"__clsName": NSStringFromClass([slf class])} inContext:_context]]; 441 | } else { 442 | [argList addObject:[JPBoxing boxWeakObj:slf]]; 443 | } 444 | 445 | for (NSUInteger i = 2; i < numberOfArguments; i++) { 446 | const char *argumentType = [methodSignature getArgumentTypeAtIndex:i]; 447 | switch(argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) { 448 | 449 | #define JP_FWD_ARG_CASE(_typeChar, _type) \ 450 | case _typeChar: { \ 451 | _type arg; \ 452 | [invocation getArgument:&arg atIndex:i]; \ 453 | [argList addObject:@(arg)]; \ 454 | break; \ 455 | } 456 | JP_FWD_ARG_CASE('c', char) 457 | JP_FWD_ARG_CASE('C', unsigned char) 458 | JP_FWD_ARG_CASE('s', short) 459 | JP_FWD_ARG_CASE('S', unsigned short) 460 | JP_FWD_ARG_CASE('i', int) 461 | JP_FWD_ARG_CASE('I', unsigned int) 462 | JP_FWD_ARG_CASE('l', long) 463 | JP_FWD_ARG_CASE('L', unsigned long) 464 | JP_FWD_ARG_CASE('q', long long) 465 | JP_FWD_ARG_CASE('Q', unsigned long long) 466 | JP_FWD_ARG_CASE('f', float) 467 | JP_FWD_ARG_CASE('d', double) 468 | JP_FWD_ARG_CASE('B', BOOL) 469 | case '@': { 470 | __unsafe_unretained id arg; 471 | [invocation getArgument:&arg atIndex:i]; 472 | if ([arg isKindOfClass:NSClassFromString(@"NSBlock")]) { 473 | [argList addObject:(arg ? [arg copy]: _nilObj)]; 474 | } else { 475 | [argList addObject:(arg ? arg: _nilObj)]; 476 | } 477 | break; 478 | } 479 | case '{': { 480 | NSString *typeString = extractStructName([NSString stringWithUTF8String:argumentType]); 481 | #define JP_FWD_ARG_STRUCT(_type, _transFunc) \ 482 | if ([typeString rangeOfString:@#_type].location != NSNotFound) { \ 483 | _type arg; \ 484 | [invocation getArgument:&arg atIndex:i]; \ 485 | [argList addObject:[JSValue _transFunc:arg inContext:_context]]; \ 486 | break; \ 487 | } 488 | JP_FWD_ARG_STRUCT(CGRect, valueWithRect) 489 | JP_FWD_ARG_STRUCT(CGPoint, valueWithPoint) 490 | JP_FWD_ARG_STRUCT(CGSize, valueWithSize) 491 | JP_FWD_ARG_STRUCT(NSRange, valueWithRange) 492 | 493 | @synchronized (_context) { 494 | NSDictionary *structDefine = registeredStruct[typeString]; 495 | if (structDefine) { 496 | size_t size = sizeOfStructTypes(structDefine[@"types"]); 497 | if (size) { 498 | void *ret = malloc(size); 499 | [invocation getArgument:ret atIndex:i]; 500 | NSDictionary *dict = getDictOfStruct(ret, structDefine); 501 | [argList addObject:[JSValue valueWithObject:dict inContext:_context]]; 502 | free(ret); 503 | break; 504 | } 505 | } 506 | } 507 | 508 | break; 509 | } 510 | case ':': { 511 | SEL selector; 512 | [invocation getArgument:&selector atIndex:i]; 513 | NSString *selectorName = NSStringFromSelector(selector); 514 | [argList addObject:(selectorName ? selectorName: _nilObj)]; 515 | break; 516 | } 517 | case '^': 518 | case '*': { 519 | void *arg; 520 | [invocation getArgument:&arg atIndex:i]; 521 | [argList addObject:[JPBoxing boxPointer:arg]]; 522 | break; 523 | } 524 | case '#': { 525 | Class arg; 526 | [invocation getArgument:&arg atIndex:i]; 527 | [argList addObject:[JPBoxing boxClass:arg]]; 528 | break; 529 | } 530 | default: { 531 | NSLog(@"error type %s", argumentType); 532 | break; 533 | } 534 | } 535 | } 536 | 537 | NSArray *params = _formatOCToJSList(argList); 538 | const char *returnType = [methodSignature methodReturnType]; 539 | 540 | switch (returnType[0] == 'r' ? returnType[1] : returnType[0]) { 541 | #define JP_FWD_RET_CALL_JS \ 542 | JSValue *fun = getJSFunctionInObjectHierachy(slf, JPSelectorName); \ 543 | JSValue *jsval; \ 544 | [_JSMethodForwardCallLock lock]; \ 545 | jsval = [fun callWithArguments:params]; \ 546 | [_JSMethodForwardCallLock unlock]; \ 547 | while (![jsval isNull] && ![jsval isUndefined] && [jsval hasProperty:@"__isPerformInOC"]) { \ 548 | NSArray *args = nil; \ 549 | JSValue *cb = jsval[@"cb"]; \ 550 | if ([jsval hasProperty:@"sel"]) { \ 551 | id callRet = callSelector(![jsval[@"clsName"] isUndefined] ? [jsval[@"clsName"] toString] : nil, [jsval[@"sel"] toString], jsval[@"args"], ![jsval[@"obj"] isUndefined] ? jsval[@"obj"] : nil, NO); \ 552 | args = @[[_context[@"_formatOCToJS"] callWithArguments:callRet ? @[callRet] : _formatOCToJSList(@[_nilObj])]]; \ 553 | } \ 554 | [_JSMethodForwardCallLock lock]; \ 555 | jsval = [cb callWithArguments:args]; \ 556 | [_JSMethodForwardCallLock unlock]; \ 557 | } 558 | 559 | #define JP_FWD_RET_CASE_RET(_typeChar, _type, _retCode) \ 560 | case _typeChar : { \ 561 | JP_FWD_RET_CALL_JS \ 562 | _retCode \ 563 | [invocation setReturnValue:&ret];\ 564 | break; \ 565 | } 566 | 567 | #define JP_FWD_RET_CASE(_typeChar, _type, _typeSelector) \ 568 | JP_FWD_RET_CASE_RET(_typeChar, _type, _type ret = [[jsval toObject] _typeSelector];) \ 569 | 570 | #define JP_FWD_RET_CODE_ID \ 571 | id ret = formatJSToOC(jsval); \ 572 | if (ret == _nilObj || \ 573 | ([ret isKindOfClass:[NSNumber class]] && strcmp([ret objCType], "c") == 0 && ![ret boolValue])) ret = nil; \ 574 | 575 | #define JP_FWD_RET_CODE_POINTER \ 576 | void *ret; \ 577 | id obj = formatJSToOC(jsval); \ 578 | if ([obj isKindOfClass:[JPBoxing class]]) { \ 579 | ret = [((JPBoxing *)obj) unboxPointer]; \ 580 | } 581 | 582 | #define JP_FWD_RET_CODE_CLASS \ 583 | Class ret; \ 584 | id obj = formatJSToOC(jsval); \ 585 | if ([obj isKindOfClass:[JPBoxing class]]) { \ 586 | ret = [((JPBoxing *)obj) unboxClass]; \ 587 | } 588 | 589 | #define JP_FWD_RET_CODE_SEL \ 590 | SEL ret; \ 591 | id obj = formatJSToOC(jsval); \ 592 | if ([obj isKindOfClass:[NSString class]]) { \ 593 | ret = NSSelectorFromString(obj); \ 594 | } 595 | 596 | JP_FWD_RET_CASE_RET('@', id, JP_FWD_RET_CODE_ID) 597 | JP_FWD_RET_CASE_RET('^', void*, JP_FWD_RET_CODE_POINTER) 598 | JP_FWD_RET_CASE_RET('*', void*, JP_FWD_RET_CODE_POINTER) 599 | JP_FWD_RET_CASE_RET('#', Class, JP_FWD_RET_CODE_CLASS) 600 | JP_FWD_RET_CASE_RET(':', SEL, JP_FWD_RET_CODE_SEL) 601 | 602 | JP_FWD_RET_CASE('c', char, charValue) 603 | JP_FWD_RET_CASE('C', unsigned char, unsignedCharValue) 604 | JP_FWD_RET_CASE('s', short, shortValue) 605 | JP_FWD_RET_CASE('S', unsigned short, unsignedShortValue) 606 | JP_FWD_RET_CASE('i', int, intValue) 607 | JP_FWD_RET_CASE('I', unsigned int, unsignedIntValue) 608 | JP_FWD_RET_CASE('l', long, longValue) 609 | JP_FWD_RET_CASE('L', unsigned long, unsignedLongValue) 610 | JP_FWD_RET_CASE('q', long long, longLongValue) 611 | JP_FWD_RET_CASE('Q', unsigned long long, unsignedLongLongValue) 612 | JP_FWD_RET_CASE('f', float, floatValue) 613 | JP_FWD_RET_CASE('d', double, doubleValue) 614 | JP_FWD_RET_CASE('B', BOOL, boolValue) 615 | 616 | case 'v': { 617 | JP_FWD_RET_CALL_JS 618 | break; 619 | } 620 | 621 | case '{': { 622 | NSString *typeString = extractStructName([NSString stringWithUTF8String:returnType]); 623 | #define JP_FWD_RET_STRUCT(_type, _funcSuffix) \ 624 | if ([typeString rangeOfString:@#_type].location != NSNotFound) { \ 625 | JP_FWD_RET_CALL_JS \ 626 | _type ret = [jsval _funcSuffix]; \ 627 | [invocation setReturnValue:&ret];\ 628 | break; \ 629 | } 630 | JP_FWD_RET_STRUCT(CGRect, toRect) 631 | JP_FWD_RET_STRUCT(CGPoint, toPoint) 632 | JP_FWD_RET_STRUCT(CGSize, toSize) 633 | JP_FWD_RET_STRUCT(NSRange, toRange) 634 | 635 | @synchronized (_context) { 636 | NSDictionary *structDefine = registeredStruct[typeString]; 637 | if (structDefine) { 638 | size_t size = sizeOfStructTypes(structDefine[@"types"]); 639 | JP_FWD_RET_CALL_JS 640 | void *ret = malloc(size); 641 | NSDictionary *dict = formatJSToOC(jsval); 642 | getStructDataWithDict(ret, dict, structDefine); 643 | [invocation setReturnValue:ret]; 644 | } 645 | } 646 | break; 647 | } 648 | default: { 649 | break; 650 | } 651 | } 652 | } 653 | 654 | static void _initJPOverideMethods(Class cls) { 655 | if (!_JSOverideMethods) { 656 | _JSOverideMethods = [[NSMutableDictionary alloc] init]; 657 | } 658 | if (!_JSOverideMethods[cls]) { 659 | _JSOverideMethods[(id)cls] = [[NSMutableDictionary alloc] init]; 660 | } 661 | } 662 | 663 | static void overrideMethod(Class cls, NSString *selectorName, JSValue *function, BOOL isClassMethod, const char *typeDescription) 664 | { 665 | SEL selector = NSSelectorFromString(selectorName); 666 | 667 | if (!typeDescription) { 668 | Method method = class_getInstanceMethod(cls, selector); 669 | typeDescription = (char *)method_getTypeEncoding(method); 670 | } 671 | 672 | IMP originalImp = class_respondsToSelector(cls, selector) ? class_getMethodImplementation(cls, selector) : NULL; 673 | 674 | IMP msgForwardIMP = _objc_msgForward; 675 | #if !defined(__arm64__) 676 | if (typeDescription[0] == '{') { 677 | //In some cases that returns struct, we should use the '_stret' API: 678 | //http://sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html 679 | //NSMethodSignature knows the detail but has no API to return, we can only get the info from debugDescription. 680 | NSMethodSignature *methodSignature = [NSMethodSignature signatureWithObjCTypes:typeDescription]; 681 | if ([methodSignature.debugDescription rangeOfString:@"is special struct return? YES"].location != NSNotFound) { 682 | msgForwardIMP = (IMP)_objc_msgForward_stret; 683 | } 684 | } 685 | #endif 686 | 687 | class_replaceMethod(cls, selector, msgForwardIMP, typeDescription); 688 | 689 | #pragma clang diagnostic push 690 | #pragma clang diagnostic ignored "-Wundeclared-selector" 691 | if (class_getMethodImplementation(cls, @selector(forwardInvocation:)) != (IMP)JPForwardInvocation) { 692 | IMP originalForwardImp = class_replaceMethod(cls, @selector(forwardInvocation:), (IMP)JPForwardInvocation, "v@:@"); 693 | class_addMethod(cls, @selector(ORIGforwardInvocation:), originalForwardImp, "v@:@"); 694 | } 695 | #pragma clang diagnostic pop 696 | 697 | if (class_respondsToSelector(cls, selector)) { 698 | NSString *originalSelectorName = [NSString stringWithFormat:@"ORIG%@", selectorName]; 699 | SEL originalSelector = NSSelectorFromString(originalSelectorName); 700 | if(!class_respondsToSelector(cls, originalSelector)) { 701 | class_addMethod(cls, originalSelector, originalImp, typeDescription); 702 | } 703 | } 704 | 705 | NSString *JPSelectorName = [NSString stringWithFormat:@"_JP%@", selectorName]; 706 | SEL JPSelector = NSSelectorFromString(JPSelectorName); 707 | 708 | _initJPOverideMethods(cls); 709 | _JSOverideMethods[cls][JPSelectorName] = function; 710 | 711 | class_addMethod(cls, JPSelector, msgForwardIMP, typeDescription); 712 | } 713 | 714 | #pragma mark - 715 | 716 | static id callSelector(NSString *className, NSString *selectorName, JSValue *arguments, JSValue *instance, BOOL isSuper) 717 | { 718 | if (instance) { 719 | instance = formatJSToOC(instance); 720 | if (!instance || instance == _nilObj) return @{@"__isNil": @(YES)}; 721 | } 722 | id argumentsObj = formatJSToOC(arguments); 723 | 724 | if (instance && [selectorName isEqualToString:@"toJS"]) { 725 | if ([instance isKindOfClass:[NSString class]] || [instance isKindOfClass:[NSDictionary class]] || [instance isKindOfClass:[NSArray class]]) { 726 | return _unboxOCObjectToJS(instance); 727 | } 728 | } 729 | 730 | Class cls = instance ? [instance class] : NSClassFromString(className); 731 | SEL selector = NSSelectorFromString(selectorName); 732 | 733 | if (isSuper) { 734 | NSString *superSelectorName = [NSString stringWithFormat:@"SUPER_%@", selectorName]; 735 | SEL superSelector = NSSelectorFromString(superSelectorName); 736 | 737 | Class superCls = [cls superclass]; 738 | Method superMethod = class_getInstanceMethod(superCls, selector); 739 | IMP superIMP = method_getImplementation(superMethod); 740 | 741 | class_addMethod(cls, superSelector, superIMP, method_getTypeEncoding(superMethod)); 742 | 743 | NSString *JPSelectorName = [NSString stringWithFormat:@"_JP%@", selectorName]; 744 | JSValue *overideFunction = _JSOverideMethods[superCls][JPSelectorName]; 745 | if (overideFunction) { 746 | overrideMethod(cls, superSelectorName, overideFunction, NO, NULL); 747 | } 748 | 749 | selector = superSelector; 750 | } 751 | 752 | 753 | NSMutableArray *_markArray; 754 | 755 | NSInvocation *invocation; 756 | NSMethodSignature *methodSignature; 757 | if (!_JSMethodSignatureCache) { 758 | _JSMethodSignatureCache = [[NSMutableDictionary alloc]init]; 759 | } 760 | if (instance) { 761 | [_JSMethodSignatureLock lock]; 762 | if (!_JSMethodSignatureCache[cls]) { 763 | _JSMethodSignatureCache[(id)cls] = [[NSMutableDictionary alloc]init]; 764 | } 765 | methodSignature = _JSMethodSignatureCache[cls][selectorName]; 766 | if (!methodSignature) { 767 | methodSignature = [cls instanceMethodSignatureForSelector:selector]; 768 | _JSMethodSignatureCache[cls][selectorName] = methodSignature; 769 | } 770 | [_JSMethodSignatureLock unlock]; 771 | if (!methodSignature) { 772 | NSCAssert(methodSignature, @"unrecognized selector %@ for instance %@", selectorName, instance); 773 | return nil; 774 | } 775 | invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; 776 | [invocation setTarget:instance]; 777 | } else { 778 | methodSignature = [cls methodSignatureForSelector:selector]; 779 | if (!methodSignature) { 780 | NSCAssert(methodSignature, @"unrecognized selector %@ for class %@", selectorName, className); 781 | return nil; 782 | } 783 | invocation= [NSInvocation invocationWithMethodSignature:methodSignature]; 784 | [invocation setTarget:cls]; 785 | } 786 | [invocation setSelector:selector]; 787 | 788 | NSUInteger numberOfArguments = methodSignature.numberOfArguments; 789 | for (NSUInteger i = 2; i < numberOfArguments; i++) { 790 | const char *argumentType = [methodSignature getArgumentTypeAtIndex:i]; 791 | id valObj = argumentsObj[i-2]; 792 | switch (argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) { 793 | 794 | #define JP_CALL_ARG_CASE(_typeString, _type, _selector) \ 795 | case _typeString: { \ 796 | _type value = [valObj _selector]; \ 797 | [invocation setArgument:&value atIndex:i];\ 798 | break; \ 799 | } 800 | 801 | JP_CALL_ARG_CASE('c', char, charValue) 802 | JP_CALL_ARG_CASE('C', unsigned char, unsignedCharValue) 803 | JP_CALL_ARG_CASE('s', short, shortValue) 804 | JP_CALL_ARG_CASE('S', unsigned short, unsignedShortValue) 805 | JP_CALL_ARG_CASE('i', int, intValue) 806 | JP_CALL_ARG_CASE('I', unsigned int, unsignedIntValue) 807 | JP_CALL_ARG_CASE('l', long, longValue) 808 | JP_CALL_ARG_CASE('L', unsigned long, unsignedLongValue) 809 | JP_CALL_ARG_CASE('q', long long, longLongValue) 810 | JP_CALL_ARG_CASE('Q', unsigned long long, unsignedLongLongValue) 811 | JP_CALL_ARG_CASE('f', float, floatValue) 812 | JP_CALL_ARG_CASE('d', double, doubleValue) 813 | JP_CALL_ARG_CASE('B', BOOL, boolValue) 814 | 815 | case ':': { 816 | SEL value = nil; 817 | if (valObj != _nilObj) { 818 | value = NSSelectorFromString(valObj); 819 | } 820 | [invocation setArgument:&value atIndex:i]; 821 | break; 822 | } 823 | case '{': { 824 | NSString *typeString = extractStructName([NSString stringWithUTF8String:argumentType]); 825 | JSValue *val = arguments[i-2]; 826 | #define JP_CALL_ARG_STRUCT(_type, _methodName) \ 827 | if ([typeString rangeOfString:@#_type].location != NSNotFound) { \ 828 | _type value = [val _methodName]; \ 829 | [invocation setArgument:&value atIndex:i]; \ 830 | break; \ 831 | } 832 | JP_CALL_ARG_STRUCT(CGRect, toRect) 833 | JP_CALL_ARG_STRUCT(CGPoint, toPoint) 834 | JP_CALL_ARG_STRUCT(CGSize, toSize) 835 | JP_CALL_ARG_STRUCT(NSRange, toRange) 836 | @synchronized (_context) { 837 | NSDictionary *structDefine = registeredStruct[typeString]; 838 | if (structDefine) { 839 | size_t size = sizeOfStructTypes(structDefine[@"types"]); 840 | void *ret = malloc(size); 841 | getStructDataWithDict(ret, valObj, structDefine); 842 | [invocation setArgument:ret atIndex:i]; 843 | free(ret); 844 | break; 845 | } 846 | } 847 | 848 | break; 849 | } 850 | case '*': 851 | case '^': { 852 | if ([valObj isKindOfClass:[JPBoxing class]]) { 853 | void *value = [((JPBoxing *)valObj) unboxPointer]; 854 | 855 | if (argumentType[1] == '@') { 856 | if (!_TMPMemoryPool) { 857 | _TMPMemoryPool = [[NSMutableDictionary alloc] init]; 858 | } 859 | if (!_markArray) { 860 | _markArray = [[NSMutableArray alloc] init]; 861 | } 862 | memset(value, 0, sizeof(id)); 863 | [_markArray addObject:valObj]; 864 | } 865 | 866 | [invocation setArgument:&value atIndex:i]; 867 | break; 868 | } 869 | } 870 | case '#': { 871 | if ([valObj isKindOfClass:[JPBoxing class]]) { 872 | Class value = [((JPBoxing *)valObj) unboxClass]; 873 | [invocation setArgument:&value atIndex:i]; 874 | break; 875 | } 876 | } 877 | default: { 878 | if (valObj == _nullObj) { 879 | valObj = [NSNull null]; 880 | [invocation setArgument:&valObj atIndex:i]; 881 | break; 882 | } 883 | if (valObj == _nilObj || 884 | ([valObj isKindOfClass:[NSNumber class]] && strcmp([valObj objCType], "c") == 0 && ![valObj boolValue])) { 885 | valObj = nil; 886 | [invocation setArgument:&valObj atIndex:i]; 887 | break; 888 | } 889 | if ([(JSValue *)arguments[i-2] hasProperty:@"__isBlock"]) { 890 | __autoreleasing id cb = genCallbackBlock(arguments[i-2]); 891 | [invocation setArgument:&cb atIndex:i]; 892 | } else { 893 | [invocation setArgument:&valObj atIndex:i]; 894 | } 895 | } 896 | } 897 | } 898 | 899 | [invocation invoke]; 900 | if ([_markArray count] > 0) { 901 | for (JPBoxing *box in _markArray) { 902 | void *pointer = [box unboxPointer]; 903 | id obj = *((__unsafe_unretained id *)pointer); 904 | if (obj) { 905 | @synchronized(_TMPMemoryPool) { 906 | [_TMPMemoryPool setObject:obj forKey:[NSNumber numberWithInteger:[obj hash]]]; 907 | } 908 | } 909 | } 910 | } 911 | const char *returnType = [methodSignature methodReturnType]; 912 | id returnValue; 913 | if (strncmp(returnType, "v", 1) != 0) { 914 | if (strncmp(returnType, "@", 1) == 0) { 915 | void *result; 916 | [invocation getReturnValue:&result]; 917 | 918 | //For performance, ignore the other methods prefix with alloc/new/copy/mutableCopy 919 | if ([selectorName isEqualToString:@"alloc"] || [selectorName isEqualToString:@"new"] || 920 | [selectorName isEqualToString:@"copy"] || [selectorName isEqualToString:@"mutableCopy"]) { 921 | returnValue = (__bridge_transfer id)result; 922 | } else { 923 | returnValue = (__bridge id)result; 924 | } 925 | return formatOCToJS(returnValue); 926 | 927 | } else { 928 | switch (returnType[0] == 'r' ? returnType[1] : returnType[0]) { 929 | 930 | #define JP_CALL_RET_CASE(_typeString, _type) \ 931 | case _typeString: { \ 932 | _type tempResultSet; \ 933 | [invocation getReturnValue:&tempResultSet];\ 934 | returnValue = @(tempResultSet); \ 935 | break; \ 936 | } 937 | 938 | JP_CALL_RET_CASE('c', char) 939 | JP_CALL_RET_CASE('C', unsigned char) 940 | JP_CALL_RET_CASE('s', short) 941 | JP_CALL_RET_CASE('S', unsigned short) 942 | JP_CALL_RET_CASE('i', int) 943 | JP_CALL_RET_CASE('I', unsigned int) 944 | JP_CALL_RET_CASE('l', long) 945 | JP_CALL_RET_CASE('L', unsigned long) 946 | JP_CALL_RET_CASE('q', long long) 947 | JP_CALL_RET_CASE('Q', unsigned long long) 948 | JP_CALL_RET_CASE('f', float) 949 | JP_CALL_RET_CASE('d', double) 950 | JP_CALL_RET_CASE('B', BOOL) 951 | 952 | case '{': { 953 | NSString *typeString = extractStructName([NSString stringWithUTF8String:returnType]); 954 | #define JP_CALL_RET_STRUCT(_type, _methodName) \ 955 | if ([typeString rangeOfString:@#_type].location != NSNotFound) { \ 956 | _type result; \ 957 | [invocation getReturnValue:&result]; \ 958 | return [JSValue _methodName:result inContext:_context]; \ 959 | } 960 | JP_CALL_RET_STRUCT(CGRect, valueWithRect) 961 | JP_CALL_RET_STRUCT(CGPoint, valueWithPoint) 962 | JP_CALL_RET_STRUCT(CGSize, valueWithSize) 963 | JP_CALL_RET_STRUCT(NSRange, valueWithRange) 964 | @synchronized (_context) { 965 | NSDictionary *structDefine = registeredStruct[typeString]; 966 | if (structDefine) { 967 | size_t size = sizeOfStructTypes(structDefine[@"types"]); 968 | void *ret = malloc(size); 969 | [invocation getReturnValue:ret]; 970 | NSDictionary *dict = getDictOfStruct(ret, structDefine); 971 | free(ret); 972 | return dict; 973 | } 974 | } 975 | break; 976 | } 977 | case '*': 978 | case '^': { 979 | void *result; 980 | [invocation getReturnValue:&result]; 981 | returnValue = formatOCToJS([JPBoxing boxPointer:result]); 982 | break; 983 | } 984 | case '#': { 985 | Class result; 986 | [invocation getReturnValue:&result]; 987 | returnValue = formatOCToJS([JPBoxing boxClass:result]); 988 | break; 989 | } 990 | } 991 | return returnValue; 992 | } 993 | } 994 | return nil; 995 | } 996 | 997 | #pragma mark - 998 | 999 | static id genCallbackBlock(JSValue *jsVal) 1000 | { 1001 | #define BLK_DEFINE_1 cb = ^id(void *p0) { 1002 | #define BLK_DEFINE_2 cb = ^id(void *p0, void *p1) { 1003 | #define BLK_DEFINE_3 cb = ^id(void *p0, void *p1, void *p2) { 1004 | #define BLK_DEFINE_4 cb = ^id(void *p0, void *p1, void *p2, void *p3) { 1005 | #define BLK_INIT_PARAMETERS NSMutableArray *list = [[NSMutableArray alloc] init]; 1006 | 1007 | #define BLK_ADD_OBJ(_paramName) [list addObject:formatOCToJS((__bridge id)_paramName)]; 1008 | #define BLK_ADD_INT(_paramName) [list addObject:formatOCToJS([NSNumber numberWithLongLong:(long long)_paramName])]; 1009 | 1010 | #define BLK_TRAITS_ARG(_idx, _paramName) \ 1011 | if (blockTypeIsObject(trim(argTypes[_idx]))) { \ 1012 | BLK_ADD_OBJ(_paramName) \ 1013 | } else { \ 1014 | BLK_ADD_INT(_paramName) \ 1015 | } \ 1016 | 1017 | #define BLK_END \ 1018 | JSValue *ret = [jsVal[@"cb"] callWithArguments:list]; \ 1019 | return formatJSToOC(ret); \ 1020 | }; 1021 | 1022 | NSArray *argTypes = [[jsVal[@"args"] toString] componentsSeparatedByString:@","]; 1023 | NSInteger count = argTypes.count; 1024 | id cb; 1025 | if (count == 1) { 1026 | BLK_DEFINE_1 1027 | BLK_INIT_PARAMETERS 1028 | BLK_TRAITS_ARG(0, p0) 1029 | BLK_END 1030 | } 1031 | if (count == 2) { 1032 | BLK_DEFINE_2 1033 | BLK_INIT_PARAMETERS 1034 | BLK_TRAITS_ARG(0, p0) 1035 | BLK_TRAITS_ARG(1, p1) 1036 | BLK_END 1037 | } 1038 | if (count == 3) { 1039 | BLK_DEFINE_3 1040 | BLK_INIT_PARAMETERS 1041 | BLK_TRAITS_ARG(0, p0) 1042 | BLK_TRAITS_ARG(1, p1) 1043 | BLK_TRAITS_ARG(2, p2) 1044 | BLK_END 1045 | } 1046 | if (count == 4) { 1047 | BLK_DEFINE_4 1048 | BLK_INIT_PARAMETERS 1049 | BLK_TRAITS_ARG(0, p0) 1050 | BLK_TRAITS_ARG(1, p1) 1051 | BLK_TRAITS_ARG(2, p2) 1052 | BLK_TRAITS_ARG(3, p3) 1053 | BLK_END 1054 | } 1055 | return cb; 1056 | } 1057 | 1058 | #pragma mark - Struct 1059 | 1060 | static int sizeOfStructTypes(NSString *structTypes) 1061 | { 1062 | const char *types = [structTypes cStringUsingEncoding:NSUTF8StringEncoding]; 1063 | int index = 0; 1064 | int size = 0; 1065 | while (types[index]) { 1066 | switch (types[index]) { 1067 | #define JP_STRUCT_SIZE_CASE(_typeChar, _type) \ 1068 | case _typeChar: \ 1069 | size += sizeof(_type); \ 1070 | break; 1071 | 1072 | JP_STRUCT_SIZE_CASE('c', char) 1073 | JP_STRUCT_SIZE_CASE('C', unsigned char) 1074 | JP_STRUCT_SIZE_CASE('s', short) 1075 | JP_STRUCT_SIZE_CASE('S', unsigned short) 1076 | JP_STRUCT_SIZE_CASE('i', int) 1077 | JP_STRUCT_SIZE_CASE('I', unsigned int) 1078 | JP_STRUCT_SIZE_CASE('l', long) 1079 | JP_STRUCT_SIZE_CASE('L', unsigned long) 1080 | JP_STRUCT_SIZE_CASE('q', long long) 1081 | JP_STRUCT_SIZE_CASE('Q', unsigned long long) 1082 | JP_STRUCT_SIZE_CASE('f', float) 1083 | JP_STRUCT_SIZE_CASE('F', CGFloat) 1084 | JP_STRUCT_SIZE_CASE('N', NSInteger) 1085 | JP_STRUCT_SIZE_CASE('U', NSUInteger) 1086 | JP_STRUCT_SIZE_CASE('d', double) 1087 | JP_STRUCT_SIZE_CASE('B', BOOL) 1088 | JP_STRUCT_SIZE_CASE('*', void *) 1089 | JP_STRUCT_SIZE_CASE('^', void *) 1090 | 1091 | default: 1092 | break; 1093 | } 1094 | index ++; 1095 | } 1096 | return size; 1097 | } 1098 | 1099 | static void getStructDataWithDict(void *structData, NSDictionary *dict, NSDictionary *structDefine) 1100 | { 1101 | NSArray *itemKeys = structDefine[@"keys"]; 1102 | const char *structTypes = [structDefine[@"types"] cStringUsingEncoding:NSUTF8StringEncoding]; 1103 | int position = 0; 1104 | for (int i = 0; i < itemKeys.count; i ++) { 1105 | switch(structTypes[i]) { 1106 | #define JP_STRUCT_DATA_CASE(_typeStr, _type, _transMethod) \ 1107 | case _typeStr: { \ 1108 | int size = sizeof(_type); \ 1109 | _type val = [dict[itemKeys[i]] _transMethod]; \ 1110 | memcpy(structData + position, &val, size); \ 1111 | position += size; \ 1112 | break; \ 1113 | } 1114 | 1115 | JP_STRUCT_DATA_CASE('c', char, charValue) 1116 | JP_STRUCT_DATA_CASE('C', unsigned char, unsignedCharValue) 1117 | JP_STRUCT_DATA_CASE('s', short, shortValue) 1118 | JP_STRUCT_DATA_CASE('S', unsigned short, unsignedShortValue) 1119 | JP_STRUCT_DATA_CASE('i', int, intValue) 1120 | JP_STRUCT_DATA_CASE('I', unsigned int, unsignedIntValue) 1121 | JP_STRUCT_DATA_CASE('l', long, longValue) 1122 | JP_STRUCT_DATA_CASE('L', unsigned long, unsignedLongValue) 1123 | JP_STRUCT_DATA_CASE('q', long long, longLongValue) 1124 | JP_STRUCT_DATA_CASE('Q', unsigned long long, unsignedLongLongValue) 1125 | JP_STRUCT_DATA_CASE('f', float, floatValue) 1126 | JP_STRUCT_DATA_CASE('d', double, doubleValue) 1127 | JP_STRUCT_DATA_CASE('B', BOOL, boolValue) 1128 | JP_STRUCT_DATA_CASE('N', NSInteger, integerValue) 1129 | JP_STRUCT_DATA_CASE('U', NSUInteger, unsignedIntegerValue) 1130 | 1131 | case 'F': { 1132 | int size = sizeof(CGFloat); 1133 | CGFloat val; 1134 | if (size == sizeof(double)) { 1135 | val = [dict[itemKeys[i]] doubleValue]; 1136 | } else { 1137 | val = [dict[itemKeys[i]] floatValue]; 1138 | } 1139 | memcpy(structData + position, &val, size); 1140 | position += size; 1141 | break; 1142 | } 1143 | 1144 | case '*': 1145 | case '^': { 1146 | int size = sizeof(void *); 1147 | void *val = [(JPBoxing *)dict[itemKeys[i]] unboxPointer]; 1148 | memcpy(structData + position, &val, size); 1149 | break; 1150 | } 1151 | 1152 | } 1153 | } 1154 | } 1155 | 1156 | static NSDictionary *getDictOfStruct(void *structData, NSDictionary *structDefine) 1157 | { 1158 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 1159 | NSArray *itemKeys = structDefine[@"keys"]; 1160 | const char *structTypes = [structDefine[@"types"] cStringUsingEncoding:NSUTF8StringEncoding]; 1161 | int position = 0; 1162 | 1163 | for (int i = 0; i < itemKeys.count; i ++) { 1164 | switch(structTypes[i]) { 1165 | #define JP_STRUCT_DICT_CASE(_typeName, _type) \ 1166 | case _typeName: { \ 1167 | size_t size = sizeof(_type); \ 1168 | _type *val = malloc(size); \ 1169 | memcpy(val, structData + position, size); \ 1170 | [dict setObject:@(*val) forKey:itemKeys[i]]; \ 1171 | free(val); \ 1172 | position += size; \ 1173 | break; \ 1174 | } 1175 | JP_STRUCT_DICT_CASE('c', char) 1176 | JP_STRUCT_DICT_CASE('C', unsigned char) 1177 | JP_STRUCT_DICT_CASE('s', short) 1178 | JP_STRUCT_DICT_CASE('S', unsigned short) 1179 | JP_STRUCT_DICT_CASE('i', int) 1180 | JP_STRUCT_DICT_CASE('I', unsigned int) 1181 | JP_STRUCT_DICT_CASE('l', long) 1182 | JP_STRUCT_DICT_CASE('L', unsigned long) 1183 | JP_STRUCT_DICT_CASE('q', long long) 1184 | JP_STRUCT_DICT_CASE('Q', unsigned long long) 1185 | JP_STRUCT_DICT_CASE('f', float) 1186 | JP_STRUCT_DICT_CASE('F', CGFloat) 1187 | JP_STRUCT_DICT_CASE('N', NSInteger) 1188 | JP_STRUCT_DICT_CASE('U', NSUInteger) 1189 | JP_STRUCT_DICT_CASE('d', double) 1190 | JP_STRUCT_DICT_CASE('B', BOOL) 1191 | 1192 | case '*': 1193 | case '^': { 1194 | size_t size = sizeof(void *); 1195 | void *val = malloc(size); 1196 | memcpy(val, structData + position, size); 1197 | [dict setObject:[JPBoxing boxPointer:val] forKey:itemKeys[i]]; 1198 | position += size; 1199 | break; 1200 | } 1201 | 1202 | } 1203 | } 1204 | return dict; 1205 | } 1206 | 1207 | static NSString *extractStructName(NSString *typeEncodeString) 1208 | { 1209 | NSArray *array = [typeEncodeString componentsSeparatedByString:@"="]; 1210 | NSString *typeString = array[0]; 1211 | int firstValidIndex = 0; 1212 | for (int i = 0; i< typeString.length; i++) { 1213 | char c = [typeString characterAtIndex:i]; 1214 | if (c == '{' || c=='_') { 1215 | firstValidIndex++; 1216 | }else { 1217 | break; 1218 | } 1219 | } 1220 | return [typeString substringFromIndex:firstValidIndex]; 1221 | } 1222 | 1223 | #pragma mark - Utils 1224 | 1225 | static NSString *trim(NSString *string) 1226 | { 1227 | return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 1228 | } 1229 | 1230 | static BOOL blockTypeIsObject(NSString *typeString) 1231 | { 1232 | return [typeString rangeOfString:@"*"].location != NSNotFound || [typeString isEqualToString:@"id"]; 1233 | } 1234 | 1235 | #pragma mark - Object format 1236 | 1237 | static id formatOCToJS(id obj) 1238 | { 1239 | if ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]]) { 1240 | return _wrapObj([JPBoxing boxObj:obj]); 1241 | } 1242 | if ([obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:NSClassFromString(@"NSBlock")] || [obj isKindOfClass:[JSValue class]]) { 1243 | return obj; 1244 | } 1245 | return _wrapObj(obj); 1246 | } 1247 | 1248 | static id formatJSToOC(JSValue *jsval) 1249 | { 1250 | id obj = [jsval toObject]; 1251 | if (!obj || [obj isKindOfClass:[NSNull class]]) return _nilObj; 1252 | 1253 | if ([obj isKindOfClass:[JPBoxing class]]) return [obj unbox]; 1254 | if ([obj isKindOfClass:[NSArray class]]) { 1255 | NSMutableArray *newArr = [[NSMutableArray alloc] init]; 1256 | for (int i = 0; i < [obj count]; i ++) { 1257 | [newArr addObject:formatJSToOC(jsval[i])]; 1258 | } 1259 | return newArr; 1260 | } 1261 | if ([obj isKindOfClass:[NSDictionary class]]) { 1262 | if (obj[@"__obj"]) { 1263 | id ocObj = [obj objectForKey:@"__obj"]; 1264 | if ([ocObj isKindOfClass:[JPBoxing class]]) return [ocObj unbox]; 1265 | return ocObj; 1266 | } 1267 | NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init]; 1268 | for (NSString *key in [obj allKeys]) { 1269 | [newDict setObject:formatJSToOC(jsval[key]) forKey:key]; 1270 | } 1271 | return newDict; 1272 | } 1273 | return obj; 1274 | } 1275 | 1276 | static id _formatOCToJSList(NSArray *list) 1277 | { 1278 | NSMutableArray *arr = [NSMutableArray new]; 1279 | for (id obj in list) { 1280 | [arr addObject:formatOCToJS(obj)]; 1281 | } 1282 | return arr; 1283 | } 1284 | 1285 | static NSDictionary *_wrapObj(id obj) 1286 | { 1287 | if (!obj || obj == _nilObj) { 1288 | return @{@"__isNil": @(YES)}; 1289 | } 1290 | return @{@"__obj": obj}; 1291 | } 1292 | 1293 | static id _unboxOCObjectToJS(id obj) 1294 | { 1295 | if ([obj isKindOfClass:[NSArray class]]) { 1296 | NSMutableArray *newArr = [[NSMutableArray alloc] init]; 1297 | for (int i = 0; i < [obj count]; i ++) { 1298 | [newArr addObject:_unboxOCObjectToJS(obj[i])]; 1299 | } 1300 | return newArr; 1301 | } 1302 | if ([obj isKindOfClass:[NSDictionary class]]) { 1303 | NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init]; 1304 | for (NSString *key in [obj allKeys]) { 1305 | [newDict setObject:_unboxOCObjectToJS(obj[key]) forKey:key]; 1306 | } 1307 | return newDict; 1308 | } 1309 | if ([obj isKindOfClass:[NSString class]] ||[obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:NSClassFromString(@"NSBlock")]) { 1310 | return obj; 1311 | } 1312 | return _wrapObj(obj); 1313 | } 1314 | @end 1315 | 1316 | 1317 | @implementation JPExtension 1318 | 1319 | + (void)main:(JSContext *)context{} 1320 | 1321 | + (void *)formatPointerJSToOC:(JSValue *)val 1322 | { 1323 | id obj = [val toObject]; 1324 | if ([obj isKindOfClass:[NSDictionary class]]) { 1325 | if (obj[@"__obj"] && [obj[@"__obj"] isKindOfClass:[JPBoxing class]]) { 1326 | return [(JPBoxing *)(obj[@"__obj"]) unboxPointer]; 1327 | } else { 1328 | return NULL; 1329 | } 1330 | } else if (![val toBool]) { 1331 | return NULL; 1332 | } else{ 1333 | return [((JPBoxing *)[val toObject]) unboxPointer]; 1334 | } 1335 | } 1336 | 1337 | + (id)formatPointerOCToJS:(void *)pointer 1338 | { 1339 | return formatOCToJS([JPBoxing boxPointer:pointer]); 1340 | } 1341 | 1342 | + (id)formatJSToOC:(JSValue *)val 1343 | { 1344 | if (![val toBool]) { 1345 | return nil; 1346 | } 1347 | return formatJSToOC(val); 1348 | } 1349 | 1350 | + (id)formatOCToJS:(id)obj 1351 | { 1352 | return [[JSContext currentContext][@"_formatOCToJS"] callWithArguments:@[formatOCToJS(obj)]]; 1353 | } 1354 | 1355 | + (int)sizeOfStructTypes:(NSString *)structTypes 1356 | { 1357 | return sizeOfStructTypes(structTypes); 1358 | } 1359 | 1360 | + (void)getStructDataWidthDict:(void *)structData dict:(NSDictionary *)dict structDefine:(NSDictionary *)structDefine 1361 | { 1362 | return getStructDataWithDict(structData, dict, structDefine); 1363 | } 1364 | 1365 | + (NSDictionary *)getDictOfStruct:(void *)structData structDefine:(NSDictionary *)structDefine 1366 | { 1367 | return getDictOfStruct(structData, structDefine); 1368 | } 1369 | @end 1370 | --------------------------------------------------------------------------------