Skip to content

Commit

Permalink
[TIMOB-25862] Parity: Support async Ti.UI.Webview.evalJS call on Andr…
Browse files Browse the repository at this point in the history
…oid & iOS (tidev#9889)

* Add an async variant of Ti.UI.WebView.evalJS
* Update docs to include async callback info to Ti.IOStream read/write
* Handle evalJS in async fashion when not invoked from UI
* Add Josh's thread/runnable for wrapping sync read/writes on main thread
* Add async Ti.IOStream #read()/#write() to iOS
  • Loading branch information
sgtcoolguy committed Sep 27, 2018
1 parent bd716c8 commit eb9e056
Show file tree
Hide file tree
Showing 11 changed files with 781 additions and 744 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.appcelerator.kroll.annotations.Kroll;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.titanium.io.TiStream;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.util.TiConvert;
import org.appcelerator.titanium.util.TiStreamHelper;

Expand Down Expand Up @@ -374,86 +373,26 @@ public boolean isConnected()

// TiStream interface methods
@Kroll.method
public int read(Object args[]) throws IOException
//public void read(BufferProxy buffer)
//public void read(BufferProxy buffer, KrollFunction resultsCallback)
//public void read(BufferProxy buffer, int offset, int length)
//public void read(BufferProxy buffer, int offset, int length, KrollFunction resultsCallback)
public int read(Object args[]) throws Exception
{
if (!isConnected()) {
throw new IOException("Unable to read from socket, not connected");
}

BufferProxy bufferProxy = null;
int offset = 0;
int length = 0;

if (args.length == 1 || args.length == 3) {
if (args.length > 0) {
if (args[0] instanceof BufferProxy) {
bufferProxy = (BufferProxy) args[0];
length = bufferProxy.getLength();

} else {
throw new IllegalArgumentException("Invalid buffer argument");
}
}

if (args.length == 3) {
if (args[1] instanceof Integer) {
offset = ((Integer) args[1]).intValue();

} else if (args[1] instanceof Double) {
offset = ((Double) args[1]).intValue();

} else {
throw new IllegalArgumentException("Invalid offset argument");
}

if (args[2] instanceof Integer) {
length = ((Integer) args[2]).intValue();

} else if (args[2] instanceof Double) {
length = ((Double) args[2]).intValue();

} else {
throw new IllegalArgumentException("Invalid length argument");
}
}

} else {
throw new IllegalArgumentException("Invalid number of arguments");
}

// Attempt to read from the socket.
final BufferProxy finalBufferProxy = bufferProxy;
final int finalOffset = offset;
final int finalLength = length;
final RunnableResult finalRunnableResult = new RunnableResult();
Runnable runnable = new Runnable() {
@Override
public void run()
{
try {
finalRunnableResult.streamedByteCount =
TiStreamHelper.read(clientSocket.getInputStream(), finalBufferProxy, finalOffset, finalLength);
} catch (Exception ex) {
finalRunnableResult.exception = ex;
}
}
};
if (TiApplication.isUIThread()) {
try {
Thread thread = new Thread(runnable);
thread.start();
thread.join();
} catch (Exception ex) {
finalRunnableResult.exception = ex;
}
} else {
runnable.run();
}
return TiStreamHelper.readTiStream(TAG, getKrollObject(), this, args);
}

// If the above read failed, then update the socket state and throw an exception.
if (finalRunnableResult.exception != null) {
finalRunnableResult.exception.printStackTrace();
String message = finalRunnableResult.exception.getMessage();
public int readSync(Object bufferProxy, int offset, int length) throws IOException
{
try {
return TiStreamHelper.read(clientSocket.getInputStream(), (BufferProxy) bufferProxy, offset, length);
} catch (IOException e) {
e.printStackTrace();
String message = e.getMessage();
if (message == null) {
message = "Unknown Error";
}
Expand All @@ -463,102 +402,36 @@ public void run()
}
throw ex;
}

// The read was successful. Return the number of bytes read.
return finalRunnableResult.streamedByteCount;
}

@Kroll.method
public int write(Object args[]) throws IOException
//public void write(BufferProxy buffer)
//public void write(BufferProxy buffer, KrollFunction resultsCallback)
//public void write(BufferProxy buffer, int offset, int length)
//public void write(BufferProxy buffer, int offset, int length, KrollFunction resultsCallback)
public int write(Object args[]) throws Exception
{
if (!isConnected()) {
throw new IOException("Unable to write to socket, not connected");
}

BufferProxy bufferProxy = null;
int offset = 0;
int length = 0;

if (args.length == 1 || args.length == 3) {
if (args.length > 0) {
if (args[0] instanceof BufferProxy) {
bufferProxy = (BufferProxy) args[0];
length = bufferProxy.getLength();

} else {
throw new IllegalArgumentException("Invalid buffer argument");
}
}

if (args.length == 3) {
if (args[1] instanceof Integer) {
offset = ((Integer) args[1]).intValue();

} else if (args[1] instanceof Double) {
offset = ((Double) args[1]).intValue();

} else {
throw new IllegalArgumentException("Invalid offset argument");
}

if (args[2] instanceof Integer) {
length = ((Integer) args[2]).intValue();

} else if (args[2] instanceof Double) {
length = ((Double) args[2]).intValue();

} else {
throw new IllegalArgumentException("Invalid length argument");
}
}

} else {
throw new IllegalArgumentException("Invalid number of arguments");
}

// Write to the socket.
final BufferProxy finalBufferProxy = bufferProxy;
final int finalOffset = offset;
final int finalLength = length;
final RunnableResult finalRunnableResult = new RunnableResult();
Runnable runnable = new Runnable() {
@Override
public void run()
{
try {
finalRunnableResult.streamedByteCount = TiStreamHelper.write(
clientSocket.getOutputStream(), finalBufferProxy, finalOffset, finalLength);
} catch (Exception ex) {
finalRunnableResult.exception = ex;
}
}
};
if (TiApplication.isUIThread()) {
try {
Thread thread = new Thread(runnable);
thread.start();
thread.join();
} catch (Exception ex) {
finalRunnableResult.exception = ex;
}
} else {
runnable.run();
}
return TiStreamHelper.writeTiStream(TAG, getKrollObject(), this, args);
}

// If the above write failed, then update the socket state and throw an exception.
if (finalRunnableResult.exception != null) {
finalRunnableResult.exception.printStackTrace();
String message = finalRunnableResult.exception.getMessage();
public int writeSync(Object buffer, int offset, int length) throws IOException
{
try {
return TiStreamHelper.write(clientSocket.getOutputStream(), (BufferProxy) buffer, offset, length);
} catch (IOException e) {
e.printStackTrace();
String message = e.getMessage();
if (message == null) {
message = "Unknown Error";
}
IOException ex = new IOException("Unable to write to socket. Reason: " + message);
updateState(SocketModule.ERROR, "error", buildErrorCallbackArgs(ex.getMessage(), 0));
throw ex;
}

// The write was successful. Return the number of bytes written.
return finalRunnableResult.streamedByteCount;
}

@Kroll.method
Expand Down Expand Up @@ -601,14 +474,4 @@ public String getApiName()
{
return "Ti.Network.Socket.TCP";
}

/** Private class used to capture async results of the "TCPProxy" read() and write() methods. */
private static class RunnableResult
{
/** The number of bytes read/written to/from the socket if successful. */
int streamedByteCount;

/** Provides the exception error that occurred if failed. Set to null if read/write was successful. */
Exception exception;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2010 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2010-2018 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
Expand All @@ -18,18 +18,38 @@ public interface TiStream {
* Refer to <a href="https://wiki.appcelerator.org/display/guides/Stream+Spec">Stream Spec</a> for more details.
* @param args arguments passed in. Must match the arguments listed in the <a href="https://wiki.appcelerator.org/display/guides/Stream+Spec">Stream Spec</a>.
* @return number of bytes read, -1 if no data is available.
* @throws IOException on error.
* @throws Exception on error.
*/
int read(Object args[]) throws IOException;
int read(Object args[]) throws Exception;

/**
* [readSync description]
* @param bufferProxy Expected to be a BufferProxy, but due to dependency cycle declared as Object
* @param offset [description]
* @param length [description]
* @return [description]
* @throws IOException [description]
*/
int readSync(Object bufferProxy, int offset, int length) throws IOException;

/**
* Implementing classes should use this method to write data from a buffer to this stream.
* Refer to <a href="https://wiki.appcelerator.org/display/guides/Stream+Spec">Stream Spec</a> for more details.
* @param args arguments passed in. Must match the arguments listed in the <a href="https://wiki.appcelerator.org/display/guides/Stream+Spec">Stream Spec</a>.
* @return number of bytes written, -1 if no data is available.
* @throws IOException on error.
* @throws Exception on error.
*/
int write(Object args[]) throws Exception;

/**
* [writeSync description]
* @param bufferProxy Expected to be a BufferProxy, but due to dependency cycle declared as Object
* @param offset [description]
* @param length [description]
* @return [description]
* @throws IOException [description]
*/
int write(Object args[]) throws IOException;
int writeSync(Object bufferProxy, int offset, int length) throws IOException;

/**
* @return true if the stream is writable, false otherwise.
Expand Down

0 comments on commit eb9e056

Please sign in to comment.