{"action":"created","issue":{"url":"https://api.github.com/repos/facebook/react-native/issues/1180","labels_url":"https://api.github.com/repos/facebook/react-native/issues/1180/labels{/name}","comments_url":"https://api.github.com/repos/facebook/react-native/issues/1180/comments","events_url":"https://api.github.com/repos/facebook/react-native/issues/1180/events","html_url":"https://github.com/facebook/react-native/pull/1180","id":73688107,"number":1180,"title":"[JS Executors] Add ability to execute non-nodeJS javascript with JS executors","user":{"login":"pj4533","id":110283,"avatar_url":"https://avatars.githubusercontent.com/u/110283?v=3","gravatar_id":"","url":"https://api.github.com/users/pj4533","html_url":"https://github.com/pj4533","followers_url":"https://api.github.com/users/pj4533/followers","following_url":"https://api.github.com/users/pj4533/following{/other_user}","gists_url":"https://api.github.com/users/pj4533/gists{/gist_id}","starred_url":"https://api.github.com/users/pj4533/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pj4533/subscriptions","organizations_url":"https://api.github.com/users/pj4533/orgs","repos_url":"https://api.github.com/users/pj4533/repos","events_url":"https://api.github.com/users/pj4533/events{/privacy}","received_events_url":"https://api.github.com/users/pj4533/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/facebook/react-native/labels/CLA%20Signed","name":"CLA Signed","color":"e7e7e7"},{"url":"https://api.github.com/repos/facebook/react-native/labels/GH%20Review:%20review-needed","name":"GH Review: review-needed","color":"fbca04"}],"state":"open","locked":false,"assignee":{"login":"nicklockwood","id":546885,"avatar_url":"https://avatars.githubusercontent.com/u/546885?v=3","gravatar_id":"","url":"https://api.github.com/users/nicklockwood","html_url":"https://github.com/nicklockwood","followers_url":"https://api.github.com/users/nicklockwood/followers","following_url":"https://api.github.com/users/nicklockwood/following{/other_user}","gists_url":"https://api.github.com/users/nicklockwood/gists{/gist_id}","starred_url":"https://api.github.com/users/nicklockwood/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nicklockwood/subscriptions","organizations_url":"https://api.github.com/users/nicklockwood/orgs","repos_url":"https://api.github.com/users/nicklockwood/repos","events_url":"https://api.github.com/users/nicklockwood/events{/privacy}","received_events_url":"https://api.github.com/users/nicklockwood/received_events","type":"User","site_admin":false},"milestone":null,"comments":6,"created_at":"2015-05-06T17:41:34Z","updated_at":"2015-06-22T18:42:26Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/facebook/react-native/pulls/1180","html_url":"https://github.com/facebook/react-native/pull/1180","diff_url":"https://github.com/facebook/react-native/pull/1180.diff","patch_url":"https://github.com/facebook/react-native/pull/1180.patch"},"body":"(This is my first PR here, so let me know what I am doing wrong!  Reading the guidelines, it looks like I did the indents wrong, I'll go back and fix that if you think this PR is worth merging.)\r\n\r\n\r\n## What & Why\r\n\r\nI am an objective-C iOS programmer, however the product I work on has both web and iOS versions.  For many of the views, there is logic needed around decorating various model objects.  For example, we might have several sources of a persons' work history.  There might be duplicates between the sources, so we have logic to know when a given 'work' model is a duplicate, and how to merge work model objects together.  Currently this logic is duplicated in the front-end client code of the web application and the iOS application.  This duplication of logic has grown in recent months and is a constant source of issues.\r\n\r\n## Goal\r\n\r\nWe want to share a very basic set of functions for manipulating low level models, between a web application and an iOS application.  These functions would be written in javascript and would not rely on Node modules.\r\n\r\n## Solution\r\n\r\nI looked into ReactNative and really liked how it abstracted *how* the javascript executes (currently JavaScriptCore vs WebViews).  Rather than duplicating this functionality, along with a bunch of the other string and object helper functions, I tried to use ReactNative to accomplish this sharing of code.  \r\n\r\nI created a totally normal objective-c iOS application using the wizard, and added a single .js file to the xcodeproj containing:\r\n\r\n```javascript\r\ndecorator = function(json) {\r\n   if (typeof json == \"string\") {\r\n      data = JSON.parse(json);\r\n   } else {\r\n      data = json;\r\n   }\r\n\r\n   if (data) {\r\n      data.decorated_field = \"I've been decorated\";\r\n   }\r\n   return JSON.stringify(data);\r\n}  \r\n```\r\n\r\nThen in the view controller I added this code:\r\n\r\n```objc\r\n    NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@\"foo\" ofType: @\"js\"];\r\n    NSString *script = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];\r\n    _scriptURL = [NSURL URLWithString:path];\r\n    \r\n    _executor = RCTCreateExecutor(RCTContextExecutor.class);\r\n\r\n    [_executor executeApplicationScript:script sourceURL:_scriptURL onComplete:^(NSError *error) {\r\n        NSString* execString = @\"decorator({model_field:\\\"foo\\\"})\";\r\n        [_executor executeJSString:execString context:RCTGetExecutorID(_executor) callback:^(id json, NSError *error) {\r\n            NSLog(@\"JSON: %@\", json);\r\n        }];\r\n    }];\r\n```\r\n\r\nThis allows me to use the ReactNative executor functionality to run that decorator function in the javascript file, from objective C.   Giving me the decorated output:\r\n\r\n```\r\n{\"model_field\":\"foo\",\"decorated_field\":\"I've been decorated\"}\r\n```\r\n\r\nIn this way, this javascript file could be stored in a submodule and used directly from the web application, or from the iOS application.  Currently, I think it would be easiest to just embed the javascript in the binary for iOS, but conceivably it could be stored on a server and downloaded dynamically.\r\n\r\n## The Pull Request\r\n\r\nThe changes I had to make were to allow direct execution of the javascript functions, rather than forcing the use of nodeJS.  I didn't change the existing API, but rather added the new ```executeJSString:context:callback``` function.  I abstracted the shared code in the ```executeJSCall``` function a bit, and tried to make it a bit cleaner.   The only real difference would be in the way the profiling is done, it no longer tracks the method & name that is passed to the ```executeJSCall```, but rather just the string that the executor ends up executing.   \r\n\r\n\r\nThoughts?\r\n"},"comment":{"url":"https://api.github.com/repos/facebook/react-native/issues/comments/114212903","html_url":"https://github.com/facebook/react-native/pull/1180#issuecomment-114212903","issue_url":"https://api.github.com/repos/facebook/react-native/issues/1180","id":114212903,"user":{"login":"ohwutup","id":2587018,"avatar_url":"https://avatars.githubusercontent.com/u/2587018?v=3","gravatar_id":"","url":"https://api.github.com/users/ohwutup","html_url":"https://github.com/ohwutup","followers_url":"https://api.github.com/users/ohwutup/followers","following_url":"https://api.github.com/users/ohwutup/following{/other_user}","gists_url":"https://api.github.com/users/ohwutup/gists{/gist_id}","starred_url":"https://api.github.com/users/ohwutup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ohwutup/subscriptions","organizations_url":"https://api.github.com/users/ohwutup/orgs","repos_url":"https://api.github.com/users/ohwutup/repos","events_url":"https://api.github.com/users/ohwutup/events{/privacy}","received_events_url":"https://api.github.com/users/ohwutup/received_events","type":"User","site_admin":false},"created_at":"2015-06-22T18:42:26Z","updated_at":"2015-06-22T18:42:26Z","body":"+1"}}