JavaScriptCore jail as alternative for Otto vm
This commit is contained in:
parent
afd7fca6d8
commit
8886bfd5d0
1
.env
1
.env
|
@ -7,3 +7,4 @@ MAINNET_NETWORKS_ENABLED=1
|
|||
ERC20_ENABLED=1
|
||||
OFFLINE_INBOX_ENABLED=0
|
||||
LOG_LEVEL=debug
|
||||
JSC_ENABLED=1
|
||||
|
|
|
@ -7,3 +7,4 @@ MAINNET_NETWORKS_ENABLED=1
|
|||
ERC20_ENABLED=1
|
||||
OFFLINE_INBOX_ENABLED=0
|
||||
LOG_LEVEL=debug
|
||||
JSC_ENABLED=1
|
||||
|
|
|
@ -7,3 +7,4 @@ MAINNET_NETWORKS_ENABLED=0
|
|||
ERC20_ENABLED=0
|
||||
OFFLINE_INBOX_ENABLED=0
|
||||
LOG_LEVEL=info
|
||||
JSC_ENABLED=0
|
||||
|
|
|
@ -49,7 +49,12 @@ public class MainApplication extends MultiDexApplication implements ReactApplica
|
|||
devCluster = true;
|
||||
}
|
||||
|
||||
StatusPackage statusPackage = new StatusPackage(BuildConfig.DEBUG, devCluster);
|
||||
boolean jscEnabled = false;
|
||||
if (BuildConfig.JSC_ENABLED == "1") {
|
||||
jscEnabled = true;
|
||||
}
|
||||
|
||||
StatusPackage statusPackage = new StatusPackage(BuildConfig.DEBUG, devCluster, jscEnabled);
|
||||
Function<String, String> callRPC = statusPackage.getCallRPC();
|
||||
List<ReactPackage> packages = new ArrayList<ReactPackage>(Arrays.asList(
|
||||
new MainReactPackage(),
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
22118DE1207A419FBFE7B62D /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CD48A32459B64E96843BB238 /* libRealmReact.a */; };
|
||||
25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */; };
|
||||
3E15DFEC1F6F4D7CAE088F49 /* libTcpSockets.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C2A4E93F6B154AEFA3485B45 /* libTcpSockets.a */; };
|
||||
4C16DE0C1F89508700AA10DB /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */; };
|
||||
4D3D740D5EFA4F8592B048D7 /* libBVLinearGradient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF1CD4C3D1254774ACCAE4E8 /* libBVLinearGradient.a */; };
|
||||
4FFAE7B0414A463991039A2E /* libRNRandomBytes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C55F15EB4D4DAF9202A662 /* libRNRandomBytes.a */; };
|
||||
5974D2035B8B47E0946B63B6 /* libRNFIRMessaging.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F752F17B1E04216B1337A72 /* libRNFIRMessaging.a */; };
|
||||
|
@ -515,6 +516,7 @@
|
|||
43A6FA689D844B0BAF3AA8B4 /* RCTOrientation.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTOrientation.xcodeproj; path = "../node_modules/react-native-orientation/iOS/RCTOrientation.xcodeproj"; sourceTree = "<group>"; };
|
||||
45FB5F523DE04BDE9877869C /* RNRandomBytes.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNRandomBytes.xcodeproj; path = "../node_modules/react-native-randombytes/RNRandomBytes.xcodeproj"; sourceTree = "<group>"; };
|
||||
46E2F6052EB44C698C680894 /* RNI18n.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNI18n.xcodeproj; path = "../node_modules/react-native-i18n/RNI18n.xcodeproj"; sourceTree = "<group>"; };
|
||||
4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
4E586E1B0E544F64AA9F5BD1 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
4EC426A98043452BB6F9C134 /* libRNInstabug.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNInstabug.a; sourceTree = "<group>"; };
|
||||
52E205D210BC48B7A553BB62 /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; };
|
||||
|
@ -591,6 +593,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4C16DE0C1F89508700AA10DB /* JavaScriptCore.framework in Frameworks */,
|
||||
B2DEA0D01E49E33300FA28D6 /* libRCTHttpServer.a in Frameworks */,
|
||||
925C1F481F7B73B20063DFA0 /* FirebaseCoreDiagnostics.framework in Frameworks */,
|
||||
9EE89E271E03FCB7007D3C25 /* libSplashScreen.a in Frameworks */,
|
||||
|
@ -1054,6 +1057,7 @@
|
|||
A97BA941B2FB44B4B66EE6D3 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */,
|
||||
925C1F7F1F7B73C00063DFA0 /* FirebaseMessaging.framework */,
|
||||
925C1F801F7B73C00063DFA0 /* Protobuf.framework */,
|
||||
925C1F401F7B73B20063DFA0 /* FirebaseCore.framework */,
|
||||
|
|
|
@ -15,6 +15,7 @@ android {
|
|||
dependencies {
|
||||
compile 'com.facebook.react:react-native:+'
|
||||
compile 'com.instabug.library:instabug:3+'
|
||||
compile 'com.github.ericwlange:AndroidJSCore:3.0.1'
|
||||
compile 'status-im:function:0.0.1'
|
||||
compile(group: 'status-im', name: 'status-go', version: 'develop-g6927638', ext: 'aar')
|
||||
}
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
package im.status.ethereum.module;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.status_im.status_go.Statusgo;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.liquidplayer.webkit.javascriptcore.JSContext;
|
||||
import org.liquidplayer.webkit.javascriptcore.JSException;
|
||||
import org.liquidplayer.webkit.javascriptcore.JSFunction;
|
||||
import org.liquidplayer.webkit.javascriptcore.JSValue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
class JSCJail implements Jail {
|
||||
private static final String TAG = "JSCJail";
|
||||
private String initJs;
|
||||
private Map<String, Cell> cells = new HashMap<>();
|
||||
private StatusModule module;
|
||||
|
||||
@Override
|
||||
public void initJail(String initJs) {
|
||||
this.initJs = initJs;
|
||||
}
|
||||
|
||||
JSCJail(StatusModule module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
private class Cell {
|
||||
JSContext context;
|
||||
Timer timer;
|
||||
}
|
||||
|
||||
private class Timer {
|
||||
private Map<String, ScheduledExecutorService> timers = new HashMap<>();
|
||||
|
||||
String setTimeout(JSValue callback, int interval) {
|
||||
return this.scheduleTask(callback, interval, false);
|
||||
}
|
||||
|
||||
String setInterval(JSValue callback, int interval) {
|
||||
return this.scheduleTask(callback, interval, true);
|
||||
}
|
||||
|
||||
private String scheduleTask(final JSValue callback, int interval, final boolean repeatable) {
|
||||
final String id = UUID.randomUUID().toString();
|
||||
final ScheduledExecutorService scheduler =
|
||||
Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
timers.put(id, scheduler);
|
||||
|
||||
scheduler.scheduleAtFixedRate
|
||||
(new Runnable() {
|
||||
public void run() {
|
||||
if (!repeatable) {
|
||||
scheduler.shutdown();
|
||||
timers.remove(id);
|
||||
}
|
||||
callback.toFunction().call();
|
||||
}
|
||||
}, interval, interval, TimeUnit.MILLISECONDS);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void clearInterval(String id) {
|
||||
if (!timers.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
ScheduledExecutorService scheduler = timers.get(id);
|
||||
scheduler.shutdown();
|
||||
timers.remove(id);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
for (String entry : timers.keySet()) {
|
||||
timers.get(entry).shutdown();
|
||||
}
|
||||
timers.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void addHandlers(Cell cell, final String chatId) {
|
||||
JSContext context = cell.context;
|
||||
final Timer timer = cell.timer;
|
||||
|
||||
JSFunction web3send = new JSFunction(context, "web3send") {
|
||||
public String web3send(String payload) {
|
||||
return Statusgo.CallRPC(payload);
|
||||
}
|
||||
};
|
||||
context.property("web3send", web3send);
|
||||
|
||||
JSFunction web3sendAsync = new JSFunction(context, "web3sendAsync") {
|
||||
public void web3sendAsync(final String payload, final JSValue callback) {
|
||||
Thread thread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
String result = Statusgo.CallRPC(payload);
|
||||
callback.toFunction().call(null, result);
|
||||
}
|
||||
};
|
||||
|
||||
thread.start();
|
||||
}
|
||||
};
|
||||
context.property("web3sendAsync", web3sendAsync);
|
||||
|
||||
JSFunction statusSendSignal = new JSFunction(context, "statusSendSignal") {
|
||||
public void statusSendSignal(String data) {
|
||||
JSONObject event = new JSONObject();
|
||||
JSONObject signal = new JSONObject();
|
||||
try {
|
||||
event.put("chat_id", chatId);
|
||||
event.put("data", data);
|
||||
signal.put("type", "jail.signal");
|
||||
signal.put("event", event);
|
||||
} catch (JSONException e) {
|
||||
Log.d(TAG, "Failed to construct signal JSON object: " + e.getMessage());
|
||||
}
|
||||
|
||||
module.signalEvent(signal.toString());
|
||||
}
|
||||
};
|
||||
context.property("statusSendSignal", statusSendSignal);
|
||||
|
||||
JSFunction setTimeout = new JSFunction(context, "setTimeout") {
|
||||
public String setTimeout(final JSValue callback, final int ms) {
|
||||
return timer.setTimeout(callback, ms);
|
||||
}
|
||||
};
|
||||
context.property("setTimeout", setTimeout);
|
||||
|
||||
JSFunction setInterval = new JSFunction(context, "setInterval") {
|
||||
public String setInterval(final JSValue callback, final int ms) {
|
||||
return timer.setInterval(callback, ms);
|
||||
}
|
||||
};
|
||||
context.property("setInterval", setInterval);
|
||||
|
||||
JSFunction clearInterval = new JSFunction(context, "clearInterval") {
|
||||
public void clearInterval(String id) {
|
||||
timer.clearInterval(id);
|
||||
}
|
||||
};
|
||||
context.property("clearInterval", clearInterval);
|
||||
|
||||
JSFunction statusLog = new JSFunction(context, "statusLog") {
|
||||
public void statusLog(String data) {
|
||||
Log.d("statusJSLog", data);
|
||||
}
|
||||
};
|
||||
context.property("statusLog", statusLog);
|
||||
}
|
||||
|
||||
private JSException jsException;
|
||||
|
||||
private void checkException(String label) {
|
||||
if (jsException != null) {
|
||||
jsException = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseJail(String chatId, String js) {
|
||||
Cell cell = new Cell();
|
||||
JSContext context = new JSContext();
|
||||
cell.context = context;
|
||||
cell.timer = new Timer();
|
||||
|
||||
context.setExceptionHandler(new JSContext.IJSExceptionHandler() {
|
||||
@Override
|
||||
public void handle(JSException exception) {
|
||||
jsException = exception;
|
||||
}
|
||||
});
|
||||
String web3Js = "var statusSignals = {\n" +
|
||||
" sendSignal: function (s) {statusSendSignal(s);}\n" +
|
||||
" };\n" +
|
||||
" var Web3 = require('web3');\n" +
|
||||
" var provider = {\n" +
|
||||
" send: function (payload) {\n" +
|
||||
" var result = web3send(JSON.stringify(payload));\n" +
|
||||
" return JSON.parse(result);\n" +
|
||||
" },\n" +
|
||||
" sendAsync: function (payload, callback) {\n" +
|
||||
" var wrappedCallback = function (result) {\n" +
|
||||
" //console.log(result);\n" +
|
||||
" var error = null;\n" +
|
||||
" try {\n" +
|
||||
" result = JSON.parse(result);\n" +
|
||||
" } catch (e) {\n" +
|
||||
" error = result;\n" +
|
||||
" }\n" +
|
||||
" callback(error, result);\n" +
|
||||
" };\n" +
|
||||
" web3sendAsync(JSON.stringify(payload), wrappedCallback);\n" +
|
||||
" }\n" +
|
||||
" };\n" +
|
||||
" var web3 = new Web3(provider);\n" +
|
||||
" var console = {\n" +
|
||||
" log: function (data) {\n" +
|
||||
" statusLog(data);\n" +
|
||||
" }\n" +
|
||||
" };\n" +
|
||||
" var Bignumber = require(\"bignumber.js\");\n" +
|
||||
" function bn(val){\n" +
|
||||
" return new Bignumber(val);\n" +
|
||||
" }\n";
|
||||
addHandlers(cell, chatId);
|
||||
context.evaluateScript(initJs);
|
||||
context.evaluateScript(web3Js);
|
||||
context.evaluateScript(js);
|
||||
|
||||
context.evaluateScript("var catalog = JSON.stringify(_status_catalog);");
|
||||
JSValue catalog = context.property("catalog");
|
||||
cells.put(chatId, cell);
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("result", catalog.toString());
|
||||
if (jsException != null) {
|
||||
result.put("error", jsException.toString());
|
||||
jsException = null;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.d(TAG, "Failed to construct JSON response for parseJail: " + e.getMessage());
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String callJail(String chatId, String path, String params) {
|
||||
if (!cells.containsKey(chatId)) {
|
||||
return null;
|
||||
}
|
||||
JSContext context = cells.get(chatId).context;
|
||||
JSValue call = context.property("call");
|
||||
JSValue callResult = call.toFunction().call(null, path, params);
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("result", callResult.toString());
|
||||
if (jsException != null) {
|
||||
result.put("error", jsException.toString());
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.d(TAG, "Failed to construct JSON response for callJail: " + e.getMessage());
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
for (String entry : cells.keySet()) {
|
||||
cells.get(entry).timer.reset();
|
||||
}
|
||||
cells.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package im.status.ethereum.module;
|
||||
|
||||
public interface Jail {
|
||||
void initJail(String initJs);
|
||||
String parseJail(String chatId, String js);
|
||||
String callJail(String chatId, String path, String params);
|
||||
void reset();
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package im.status.ethereum.module;
|
||||
|
||||
import com.github.status_im.status_go.Statusgo;
|
||||
|
||||
public class OttoJail implements Jail {
|
||||
@Override
|
||||
public void initJail(String initJs) {
|
||||
Statusgo.InitJail(initJs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseJail(String chatId, String js) {
|
||||
return Statusgo.Parse(chatId, js);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String callJail(String chatId, String path, String params) {
|
||||
return Statusgo.Call(chatId, path, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
|
||||
}
|
||||
}
|
|
@ -39,8 +39,9 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
private ExecutorService executor = null;
|
||||
private boolean debug;
|
||||
private boolean devCluster;
|
||||
private Jail jail;
|
||||
|
||||
StatusModule(ReactApplicationContext reactContext, boolean debug, boolean devCluster) {
|
||||
StatusModule(ReactApplicationContext reactContext, boolean debug, boolean devCluster, boolean jscEnabled) {
|
||||
super(reactContext);
|
||||
if (executor == null) {
|
||||
executor = Executors.newCachedThreadPool();
|
||||
|
@ -48,6 +49,11 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
this.debug = debug;
|
||||
this.devCluster = devCluster;
|
||||
reactContext.addLifecycleEventListener(this);
|
||||
if(jscEnabled) {
|
||||
jail = new JSCJail(this);
|
||||
} else {
|
||||
jail = new OttoJail();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -97,8 +103,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
return true;
|
||||
}
|
||||
|
||||
// Geth
|
||||
private void signalEvent(String jsonEvent) {
|
||||
|
||||
void signalEvent(String jsonEvent) {
|
||||
Log.d(TAG, "Signal event: " + jsonEvent);
|
||||
WritableMap params = Arguments.createMap();
|
||||
params.putString("jsonEvent", jsonEvent);
|
||||
|
@ -342,6 +348,9 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
jail.reset();
|
||||
|
||||
Thread thread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -467,7 +476,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
Thread thread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
Statusgo.InitJail(js);
|
||||
jail.initJail(js);
|
||||
|
||||
callback.invoke(false);
|
||||
}
|
||||
|
@ -478,7 +487,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
|
||||
@ReactMethod
|
||||
public void parseJail(final String chatId, final String js, final Callback callback) {
|
||||
Log.d(TAG, "parseJail");
|
||||
Log.d(TAG, "parseJail chatId:" + chatId);
|
||||
Log.d(TAG, js);
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
|
@ -487,7 +497,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
Thread thread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.Parse(chatId, js);
|
||||
String res = jail.parseJail(chatId, js);
|
||||
Log.d(TAG, res);
|
||||
Log.d(TAG, "endParseJail");
|
||||
callback.invoke(res);
|
||||
}
|
||||
|
@ -509,7 +520,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
@Override
|
||||
public void run() {
|
||||
Log.d(TAG, "startCallJail");
|
||||
String res = Statusgo.Call(chatId, path, params);
|
||||
String res = jail.callJail(chatId, path, params);
|
||||
Log.d(TAG, "endCallJail");
|
||||
callback.invoke(res);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@ public class StatusPackage implements ReactPackage {
|
|||
|
||||
private boolean debug;
|
||||
private boolean devCluster;
|
||||
private boolean jscEnabled;
|
||||
|
||||
public StatusPackage (boolean debug, boolean devCluster) {
|
||||
public StatusPackage (boolean debug, boolean devCluster, boolean jscEnabled) {
|
||||
this.debug = debug;
|
||||
this.devCluster = devCluster;
|
||||
this.jscEnabled = jscEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,7 +29,7 @@ public class StatusPackage implements ReactPackage {
|
|||
List<NativeModule> modules = new ArrayList<>();
|
||||
System.loadLibrary("statusgoraw");
|
||||
System.loadLibrary("statusgo");
|
||||
modules.add(new StatusModule(reactContext, this.debug, this.devCluster));
|
||||
modules.add(new StatusModule(reactContext, this.debug, this.devCluster, this.jscEnabled));
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
#import <Statusgo/Statusgo.h>
|
||||
#import "TimerJSExport.h"
|
||||
|
||||
@interface Jail : NSObject
|
||||
- (void)initJail:(NSString *)js;
|
||||
|
||||
- (NSDictionary *)parseJail:(NSString *)chatId
|
||||
withCode:(NSString *)js;
|
||||
|
||||
- (NSDictionary *)call:(NSString *)chatId
|
||||
path:(NSString *)path
|
||||
params:(NSString *)params;
|
||||
|
||||
- (void)reset;
|
||||
|
||||
@property (nonatomic) NSMutableDictionary * cells;
|
||||
@property (nonatomic) NSString * initialJs;
|
||||
@property (nonatomic) TimerJS * timer;
|
||||
|
||||
@end
|
||||
|
||||
@interface Cell : NSObject
|
||||
@property (nonatomic)JSContext * context;
|
||||
@property (nonatomic)TimerJS * timer;
|
||||
@end
|
||||
|
||||
@protocol HandlersJSExport <JSExport>
|
||||
|
||||
- (void)log:(JSValue *)data;
|
||||
- (NSString *)send:(JSValue *)payload;
|
||||
- (void)sendAsync:(JSValue *)payload;
|
||||
- (BOOL)isConnected;
|
||||
- (void)sendSignal:(JSValue *)data;
|
||||
|
||||
@end
|
||||
|
||||
@interface HandlersJs : NSObject <HandlersJSExport>
|
||||
@property (nonatomic) NSString * chatId;
|
||||
@end
|
|
@ -0,0 +1,210 @@
|
|||
#import "Jail.h"
|
||||
#import "RCTStatus.h"
|
||||
|
||||
//source: http://stackoverflow.com/a/23387659/828487
|
||||
#define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]
|
||||
|
||||
@implementation HandlersJs
|
||||
|
||||
- (void)log:(JSValue *)data
|
||||
{
|
||||
NSLog(@"jail log: %@", [data toString]);
|
||||
}
|
||||
|
||||
- (NSString *)send:(JSValue *)payload
|
||||
{
|
||||
char * result = CallRPC((char *) [[payload toString] UTF8String]);
|
||||
|
||||
return [NSString stringWithUTF8String: result];
|
||||
}
|
||||
|
||||
- (void)sendAsync:(JSValue *)args
|
||||
{
|
||||
// TODO(rasom): fix this black magic, need to figure how to pass more than one
|
||||
// parameter to sendAsync
|
||||
JSValue *payload = [args callWithArguments:@[@0]];
|
||||
JSValue *callback = [args callWithArguments:@[@1]];
|
||||
|
||||
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSString *result = [self send:payload];
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[callback callWithArguments:@[result]];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL)isConnected
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)sendSignal:(JSValue *)data
|
||||
{
|
||||
[Status jailEvent:_chatId data:[data toString]];
|
||||
}
|
||||
|
||||
- (void)setChatId:(NSString *)chatId
|
||||
{
|
||||
_chatId = chatId;
|
||||
}
|
||||
|
||||
- (void)addToContext:(JSContext *)context
|
||||
{
|
||||
[context setObject:self forKeyedSubscript:@"statusNativeHandlers"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation Cell
|
||||
@end
|
||||
|
||||
@implementation Jail
|
||||
|
||||
- (void)initJail:(NSString *)js {
|
||||
_initialJs = js;
|
||||
}
|
||||
|
||||
- (NSDictionary *)parseJail:(NSString *)chatId
|
||||
withCode:(NSString *)js {
|
||||
Cell *cell = [self createCell:chatId withCode:js];
|
||||
JSContext *context = cell.context;
|
||||
[_cells setValue:cell forKey:chatId];
|
||||
|
||||
JSValue *catalog = context[@"catalog"];;
|
||||
JSValue *exception = [context exception];
|
||||
NSString *error;
|
||||
if(exception != nil) {
|
||||
error = [exception toString];
|
||||
[context setException:nil];
|
||||
}
|
||||
NSDictionary *result = [[NSDictionary alloc] initWithObjectsAndKeys:[catalog toString], @"result", error, @"error", nil];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSDictionary *)call:(NSString *)chatId
|
||||
path:(NSString *)path
|
||||
params:(NSString *)params {
|
||||
Cell *cell = [_cells valueForKey:chatId];
|
||||
JSContext *context = cell.context;
|
||||
if(cell == nil) {
|
||||
return [[NSDictionary alloc] initWithObjectsAndKeys:nil, @"result", @"jail is not initialized", @"error", nil];
|
||||
}
|
||||
JSValue *callResult = [context[@"call"] callWithArguments:@[path, params]];
|
||||
JSValue *exception = [context exception];
|
||||
NSString *error;
|
||||
if(exception != nil) {
|
||||
error = [exception toString];
|
||||
[context setException:nil];
|
||||
}
|
||||
NSDictionary *result = [[NSDictionary alloc] initWithObjectsAndKeys:[callResult toString], @"result", error, @"error", nil];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (Cell *)createCell:(NSString *)chatId
|
||||
withCode:(NSString *)js {
|
||||
if(_cells == nil) {
|
||||
_cells = [NSMutableDictionary dictionaryWithCapacity:1];
|
||||
}
|
||||
|
||||
Cell * cell = [Cell new];
|
||||
JSContext *context = [JSContext new];
|
||||
cell.context = context;
|
||||
|
||||
HandlersJs *handlers = [HandlersJs new];
|
||||
[handlers setChatId:chatId];
|
||||
[handlers addToContext:context];
|
||||
|
||||
[self addTimer:cell];
|
||||
[context evaluateScript:_initialJs];
|
||||
|
||||
JSValue *excep = [context exception];
|
||||
NSLog(@"err1 %@", [excep toString]);
|
||||
|
||||
NSString *webJs =
|
||||
NSStringMultiline
|
||||
(
|
||||
var statusSignals = {
|
||||
sendSignal: function (s) {statusNativeHandlers.sendSignal(s);}
|
||||
};
|
||||
var setTimeout = function (fn, t) {
|
||||
var args = [fn, t];
|
||||
var getItem = function(idx) {return args[idx];};
|
||||
return jsTimer.setTimeout(getItem);
|
||||
};
|
||||
var setInterval = function (fn, t) {
|
||||
var args = [fn, t];
|
||||
var getItem = function(idx) {return args[idx];};
|
||||
return jsTimer.setInterval(getItem);
|
||||
};
|
||||
var clearInterval = function (id) {
|
||||
jsTimer.clearInterval(id);
|
||||
};
|
||||
var Web3 = require('web3');
|
||||
var provider = {
|
||||
send: function (payload) {
|
||||
var result = statusNativeHandlers.send(JSON.stringify(payload));
|
||||
return JSON.parse(result);
|
||||
},
|
||||
sendAsync: function (payload, callback) {
|
||||
var wrappedCallback = function (result) {
|
||||
console.log(result);
|
||||
var error = null;
|
||||
try {
|
||||
result = JSON.parse(result);
|
||||
} catch (e) {
|
||||
error = result;
|
||||
}
|
||||
callback(error, result);
|
||||
};
|
||||
var args = [JSON.stringify(payload), wrappedCallback];
|
||||
var getItem = function(idx) {return args[idx];};
|
||||
statusNativeHandlers.sendAsync(getItem);
|
||||
}
|
||||
};
|
||||
var web3 = new Web3(provider);
|
||||
var console = {
|
||||
log: function (data) {
|
||||
statusNativeHandlers.log(data);
|
||||
}
|
||||
};
|
||||
var Bignumber = require("bignumber.js");
|
||||
function bn(val){
|
||||
return new Bignumber(val);
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
[context evaluateScript:webJs];
|
||||
excep = [context exception];
|
||||
NSLog(@"err2 %@", [excep toString]);
|
||||
[context evaluateScript:js];
|
||||
excep = [context exception];
|
||||
NSLog(@"err3 %@", [excep toString]);
|
||||
[context evaluateScript:@"var catalog = JSON.stringify(_status_catalog);"];
|
||||
excep = [context exception];
|
||||
NSLog(@"err4 %@", [excep toString]);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)addTimer:(Cell *)cell {
|
||||
TimerJS *timer = [TimerJS new];
|
||||
cell.timer = timer;
|
||||
|
||||
[timer addToContext:cell.context];
|
||||
}
|
||||
|
||||
-(void)reset {
|
||||
NSArray *keys = [_cells allKeys];
|
||||
for (NSString *key in keys) {
|
||||
Cell *cell = [_cells valueForKey:key];
|
||||
TimerJS *timer = cell.timer;
|
||||
[timer stopTimers];
|
||||
[_cells removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,7 +1,13 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTLog.h"
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
#import "Jail.h"
|
||||
|
||||
@interface Status : NSObject <RCTBridgeModule>
|
||||
+ (void)signalEvent:(const char *) signal;
|
||||
+ (void)signalEvent:(const char *)signal;
|
||||
+ (void)jailEvent:(NSString *)chatId
|
||||
data:(NSString *)data;
|
||||
+ (BOOL)JSCEnabled;
|
||||
@property (nonatomic) Jail * jail;
|
||||
@end
|
||||
|
|
|
@ -63,6 +63,11 @@ static RCTBridge *bridge;
|
|||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
+ (BOOL)JSCEnabled
|
||||
{
|
||||
return @"1" == [ReactNativeConfig envFor:@"JSC_ENABLED"];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - Jails functions
|
||||
//////////////////////////////////////////////////////////////////// initJail
|
||||
|
@ -71,7 +76,14 @@ RCT_EXPORT_METHOD(initJail: (NSString *) js
|
|||
#if DEBUG
|
||||
NSLog(@"InitJail() method called");
|
||||
#endif
|
||||
InitJail((char *) [js UTF8String]);
|
||||
if([Status JSCEnabled]){
|
||||
if(_jail == nil) {
|
||||
_jail = [Jail new];
|
||||
}
|
||||
[_jail initJail:js];
|
||||
} else {
|
||||
InitJail((char *) [js UTF8String]);
|
||||
}
|
||||
callback(@[[NSNull null]]);
|
||||
}
|
||||
|
||||
|
@ -82,8 +94,19 @@ RCT_EXPORT_METHOD(parseJail:(NSString *)chatId
|
|||
#if DEBUG
|
||||
NSLog(@"ParseJail() method called");
|
||||
#endif
|
||||
char * result = Parse((char *) [chatId UTF8String], (char *) [js UTF8String]);
|
||||
callback(@[[NSString stringWithUTF8String: result]]);
|
||||
NSString *stringResult;
|
||||
if([Status JSCEnabled]){
|
||||
if(_jail == nil) {
|
||||
_jail = [Jail new];
|
||||
}
|
||||
NSDictionary *result = [_jail parseJail:chatId withCode:js];
|
||||
stringResult = [result bv_jsonStringWithPrettyPrint:NO];
|
||||
} else {
|
||||
char * result = Parse((char *) [chatId UTF8String], (char *) [js UTF8String]);
|
||||
stringResult = [NSString stringWithUTF8String: result];
|
||||
}
|
||||
|
||||
callback(@[stringResult]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// callJail
|
||||
|
@ -95,9 +118,21 @@ RCT_EXPORT_METHOD(callJail:(NSString *)chatId
|
|||
NSLog(@"CallJail() method called");
|
||||
#endif
|
||||
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
char * result = Call((char *) [chatId UTF8String], (char *) [path UTF8String], (char *) [params UTF8String]);
|
||||
|
||||
NSString *stringResult;
|
||||
if([Status JSCEnabled]){
|
||||
if(_jail == nil) {
|
||||
_jail = [Jail new];
|
||||
}
|
||||
NSDictionary *result = [_jail call:chatId path:path params:params];
|
||||
stringResult = [result bv_jsonStringWithPrettyPrint:NO];
|
||||
} else {
|
||||
char * result = Call((char *) [chatId UTF8String], (char *) [path UTF8String], (char *) [params UTF8String]);
|
||||
stringResult = [NSString stringWithUTF8String: result];
|
||||
}
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
callback(@[[NSString stringWithUTF8String: result]]);
|
||||
callback(@[stringResult]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -168,7 +203,7 @@ RCT_EXPORT_METHOD(startNode:(NSString *)configString) {
|
|||
[resultingConfigJson setValue:[NSNumber numberWithBool:YES] forKey:@"LogEnabled"];
|
||||
[resultingConfigJson setValue:logUrl.path forKey:@"LogFile"];
|
||||
[resultingConfigJson setValue:@"DEBUG" forKey:@"LogLevel"];
|
||||
|
||||
|
||||
if(upstreamURL != nil) {
|
||||
[resultingConfigJson setValue:[NSNumber numberWithBool:YES] forKeyPath:@"UpstreamConfig.Enabled"];
|
||||
[resultingConfigJson setValue:upstreamURL forKeyPath:@"UpstreamConfig.URL"];
|
||||
|
@ -243,14 +278,14 @@ RCT_EXPORT_METHOD(createAccount:(NSString *)password
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - Notify method
|
||||
#pragma mark - Notify method
|
||||
//////////////////////////////////////////////////////////////////// notify
|
||||
RCT_EXPORT_METHOD(notify:(NSString *)token
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
char * result = Notify((char *) [token UTF8String]);
|
||||
callback(@[[NSString stringWithUTF8String: result]]);
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
char * result = Notify((char *) [token UTF8String]);
|
||||
callback(@[[NSString stringWithUTF8String: result]]);
|
||||
#if DEBUG
|
||||
NSLog(@"Notify() method called");
|
||||
NSLog(@"Notify() method called");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -273,6 +308,9 @@ RCT_EXPORT_METHOD(login:(NSString *)address
|
|||
#if DEBUG
|
||||
NSLog(@"Login() method called");
|
||||
#endif
|
||||
if(_jail != nil) {
|
||||
[_jail reset];
|
||||
}
|
||||
char * result = Login((char *) [address UTF8String], (char *) [password UTF8String]);
|
||||
callback(@[[NSString stringWithUTF8String: result]]);
|
||||
}
|
||||
|
@ -331,13 +369,13 @@ RCT_EXPORT_METHOD(clearCookies) {
|
|||
|
||||
RCT_EXPORT_METHOD(clearStorageAPIs) {
|
||||
[[NSURLCache sharedURLCache] removeAllCachedResponses];
|
||||
|
||||
|
||||
NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
|
||||
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
|
||||
for (NSString *string in array) {
|
||||
NSLog(@"Removing %@", [path stringByAppendingPathComponent:string]);
|
||||
if ([[string pathExtension] isEqualToString:@"localstorage"])
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[path stringByAppendingPathComponent:string] error:nil];
|
||||
if ([[string pathExtension] isEqualToString:@"localstorage"])
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[path stringByAppendingPathComponent:string] error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +397,7 @@ RCT_EXPORT_METHOD(closeApplication) {
|
|||
{
|
||||
if(!signal){
|
||||
#if DEBUG
|
||||
NSLog(@"SignalEvent nil");
|
||||
NSLog(@"SignalEvent nil");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -375,4 +413,23 @@ RCT_EXPORT_METHOD(closeApplication) {
|
|||
return;
|
||||
}
|
||||
|
||||
+ (void)jailEvent:(NSString *)chatId
|
||||
data:(NSString *)data
|
||||
{
|
||||
NSData *signalData = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:signalData options:NSJSONReadingMutableContainers error:nil];
|
||||
[dict setValue:@"jail.signal" forKey:@"type"];
|
||||
NSDictionary *event = [[NSDictionary alloc] initWithObjectsAndKeys:chatId, @"chat_id", data, @"data", nil];
|
||||
[dict setValue:event forKey:@"event"];
|
||||
NSString *signal = [dict bv_jsonStringWithPrettyPrint:NO];
|
||||
#if DEBUG
|
||||
NSLog(@"SignalEventData");
|
||||
NSLog(signal);
|
||||
#endif
|
||||
[bridge.eventDispatcher sendAppEventWithName:@"gethEvent"
|
||||
body:@{@"jsonEvent": signal}];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
/* Begin PBXBuildFile section */
|
||||
206C9F3E1D474E910063E3E6 /* RCTStatus.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 206C9F3D1D474E910063E3E6 /* RCTStatus.h */; };
|
||||
206C9F401D474E910063E3E6 /* RCTStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 206C9F3F1D474E910063E3E6 /* RCTStatus.m */; };
|
||||
4C0AB2231F8A2ED700CFD175 /* Jail.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0AB2221F8A2ED700CFD175 /* Jail.m */; };
|
||||
4C16DE661F8A171B00AA10DB /* TimerJSExport.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C16DE651F8A171B00AA10DB /* TimerJSExport.m */; };
|
||||
CE4E31B11D86951A0033ED64 /* Statusgo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE4E31B01D86951A0033ED64 /* Statusgo.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -30,6 +32,10 @@
|
|||
206C9F3A1D474E910063E3E6 /* libRCTStatus.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTStatus.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
206C9F3D1D474E910063E3E6 /* RCTStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTStatus.h; sourceTree = "<group>"; };
|
||||
206C9F3F1D474E910063E3E6 /* RCTStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTStatus.m; sourceTree = "<group>"; };
|
||||
4C0AB2211F8A2EC700CFD175 /* Jail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Jail.h; sourceTree = "<group>"; };
|
||||
4C0AB2221F8A2ED700CFD175 /* Jail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Jail.m; sourceTree = "<group>"; };
|
||||
4C16DE641F8A170500AA10DB /* TimerJSExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimerJSExport.h; sourceTree = "<group>"; };
|
||||
4C16DE651F8A171B00AA10DB /* TimerJSExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TimerJSExport.m; sourceTree = "<group>"; };
|
||||
9E3F8AF21ED2CCBD0016D874 /* Instabug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Instabug.framework; path = ../../../../ios/Pods/Instabug/Instabug.framework; sourceTree = "<group>"; };
|
||||
CE4E31B01D86951A0033ED64 /* Statusgo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Statusgo.framework; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -69,6 +75,10 @@
|
|||
children = (
|
||||
206C9F3D1D474E910063E3E6 /* RCTStatus.h */,
|
||||
206C9F3F1D474E910063E3E6 /* RCTStatus.m */,
|
||||
4C16DE641F8A170500AA10DB /* TimerJSExport.h */,
|
||||
4C16DE651F8A171B00AA10DB /* TimerJSExport.m */,
|
||||
4C0AB2211F8A2EC700CFD175 /* Jail.h */,
|
||||
4C0AB2221F8A2ED700CFD175 /* Jail.m */,
|
||||
);
|
||||
name = Status;
|
||||
sourceTree = "<group>";
|
||||
|
@ -137,6 +147,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4C16DE661F8A171B00AA10DB /* TimerJSExport.m in Sources */,
|
||||
4C0AB2231F8A2ED700CFD175 /* Jail.m in Sources */,
|
||||
206C9F401D474E910063E3E6 /* RCTStatus.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
@protocol TimerJSExport <JSExport>
|
||||
|
||||
- (NSString *)setTimeout:(JSValue *)args;
|
||||
|
||||
- (void)clearInterval:(NSString *)id;
|
||||
|
||||
- (NSString *)setInterval:(JSValue *)args;
|
||||
|
||||
@end
|
||||
|
||||
@interface TimerJS : NSObject <TimerJSExport>
|
||||
- (void)addToContext:(JSContext *)context;
|
||||
- (void)stopTimers;
|
||||
@property (nonatomic) NSMutableDictionary * timers;
|
||||
@end
|
|
@ -0,0 +1,60 @@
|
|||
#import "TimerJSExport.h"
|
||||
|
||||
@implementation TimerJS
|
||||
|
||||
- (NSString *)setTimeout:(JSValue *)args {
|
||||
JSValue *callback = [args callWithArguments:@[@0]];
|
||||
double ms = [[args callWithArguments:@[@1]] toDouble];
|
||||
return [self createTimer:callback inteval:ms repeats:NO];
|
||||
}
|
||||
|
||||
- (void)clearInterval:(NSString *)id {
|
||||
NSTimer *timer = [_timers objectForKey:id];
|
||||
if(timer != nil) {
|
||||
[timer invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)setInterval:(JSValue *)args {
|
||||
JSValue *callback = [args callWithArguments:@[@0]];
|
||||
double ms = [[args callWithArguments:@[@1]] toDouble];
|
||||
return [self createTimer:callback inteval:ms repeats:YES];
|
||||
}
|
||||
|
||||
- (NSString *)createTimer:(JSValue *)callback
|
||||
inteval:(double)ms
|
||||
repeats:(BOOL)repeats {
|
||||
if (_timers == nil) {
|
||||
_timers = [NSMutableDictionary dictionaryWithCapacity:1];
|
||||
}
|
||||
|
||||
double interval = ms/1000.0;
|
||||
NSString *uuid = [[NSUUID UUID] UUIDString];
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:interval
|
||||
repeats:repeats
|
||||
block:^(NSTimer * _Nonnull timer) {
|
||||
[callback callWithArguments:nil]; }];
|
||||
[_timers setObject:timer forKey:uuid];
|
||||
});
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
- (void)addToContext:(JSContext *)context {
|
||||
[context setObject:self forKeyedSubscript:@"jsTimer"];
|
||||
}
|
||||
|
||||
- (void)stopTimers {
|
||||
NSArray *keys = [_timers allKeys];
|
||||
for (NSString *key in keys) {
|
||||
NSTimer *timer = [_timers valueForKey:key];
|
||||
[timer invalidate];
|
||||
|
||||
[_timers removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -471,20 +471,24 @@ var phoneConfig = {
|
|||
placeholder: I18n.t('phone_placeholder')
|
||||
}],
|
||||
preview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
params.phone
|
||||
)
|
||||
};
|
||||
if (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
params.phone
|
||||
)
|
||||
};
|
||||
}
|
||||
},
|
||||
shortPreview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
params.phone
|
||||
)
|
||||
};
|
||||
if (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
params.phone
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
status.command(phoneConfig);
|
||||
|
|
|
@ -300,7 +300,7 @@ I18n.translations = {
|
|||
password_placeholder2: '確認のためにパスワードを再入力してください',
|
||||
password_error: 'パスワードは6文字以上にしてください。',
|
||||
password_error1: 'パスワードが一致しません。',
|
||||
password_validation_title: 'パスワード'
|
||||
password_validation_title: 'パスワード',
|
||||
|
||||
faucet_incorrect_title: 'フォーセットが違います',
|
||||
faucet_incorrect_description: '一覧の中から一つだけ選択してください',
|
||||
|
|
|
@ -63,8 +63,8 @@ status.command({
|
|||
{
|
||||
source: {uri: uri},
|
||||
style: {
|
||||
borderRadius: 5
|
||||
marginTop: 12
|
||||
borderRadius: 5,
|
||||
marginTop: 12,
|
||||
height: 58
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
[status-im.utils.js-resources :as js-resources]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.data-store.local-storage :as local-storage]
|
||||
[status-im.bots.events :as bots-events]
|
||||
|
@ -25,7 +26,10 @@
|
|||
(status/parse-jail
|
||||
jail-id jail-resource
|
||||
(fn [jail-response]
|
||||
(re-frame/dispatch [::proceed-loading jail-id (types/json->clj jail-response)]))))))
|
||||
(let [converted (types/json->clj jail-response)]
|
||||
(re-frame/dispatch [::proceed-loading jail-id (if config/jsc-enabled?
|
||||
(update converted :result types/json->clj)
|
||||
converted)])))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::show-popup
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[status-im.utils.transducers :as transducers]
|
||||
[status-im.utils.async :as async-util]
|
||||
[status-im.react-native.js-dependencies :as rn-dependencies]
|
||||
[status-im.native-module.module :as module]))
|
||||
[status-im.native-module.module :as module]
|
||||
[status-im.utils.config :as config]))
|
||||
|
||||
;; if StatusModule is not initialized better to store
|
||||
;; calls and make them only when StatusModule is ready
|
||||
|
@ -54,9 +55,16 @@
|
|||
(defn init-jail []
|
||||
(when status
|
||||
(call-module
|
||||
(fn []
|
||||
(let [init-js (str js-res/status-js "I18n.locale = '" rn-dependencies/i18n.locale "';")]
|
||||
(.initJail status init-js #(log/debug "jail initialized")))))))
|
||||
(fn []
|
||||
(let [init-js (str js-res/status-js "I18n.locale = '" rn-dependencies/i18n.locale "'; ")
|
||||
init-js' (if config/jsc-enabled?
|
||||
(str init-js js-res/web3)
|
||||
init-js)
|
||||
log-message (str (if config/jsc-enabled?
|
||||
"JavaScriptCore"
|
||||
"OttoVM")
|
||||
" jail initialized")]
|
||||
(.initJail status init-js' #(log/debug log-message)))))))
|
||||
|
||||
(defonce listener-initialized (atom false))
|
||||
|
||||
|
@ -138,8 +146,11 @@
|
|||
cb (fn [jail-result]
|
||||
(let [result (-> jail-result
|
||||
types/json->clj
|
||||
(assoc :bot-id jail-id))]
|
||||
(callback result)))]
|
||||
(assoc :bot-id jail-id))
|
||||
result' (if config/jsc-enabled?
|
||||
(update result :result types/json->clj)
|
||||
result)]
|
||||
(callback result')))]
|
||||
(.callJail status jail-id (types/clj->json path) (types/clj->json params') cb))))))
|
||||
|
||||
;; We want the mainting (time) windowed queue of all calls to the jail
|
||||
|
|
|
@ -31,3 +31,4 @@
|
|||
string/lower-case
|
||||
keyword))
|
||||
|
||||
(def jsc-enabled? (enabled? (get-config :JSC_ENABLED 0)))
|
||||
|
|
Loading…
Reference in New Issue