From b0519c8280e572b0c41ccfa8ac4b4167d5eb09a2 Mon Sep 17 00:00:00 2001 From: Andy Street Date: Tue, 12 Jan 2016 04:51:15 -0800 Subject: [PATCH] Update WebWorkers API to return message object in onmessage Summary: public I wasn't obeying the web workers API correctly: I had missed that the message isn't sent directly but is attached to a message object in a data field. Reviewed By: lexs Differential Revision: D2811247 fb-gh-sync-id: 8e51414766e0cfe382ee9bdde8f0d66e269cb83a --- .../src/main/jni/react/JSCExecutor.cpp | 4 +-- .../src/main/jni/react/JSCWebWorker.cpp | 12 ++++++-- .../src/main/jni/react/JSCWebWorker.h | 2 ++ ReactAndroid/src/main/jni/react/Value.cpp | 28 ++++++++++++++++++- ReactAndroid/src/main/jni/react/Value.h | 11 +++++++- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/ReactAndroid/src/main/jni/react/JSCExecutor.cpp b/ReactAndroid/src/main/jni/react/JSCExecutor.cpp index aa1102294..499bbbc37 100644 --- a/ReactAndroid/src/main/jni/react/JSCExecutor.cpp +++ b/ReactAndroid/src/main/jni/react/JSCExecutor.cpp @@ -239,14 +239,14 @@ std::shared_ptr JSCExecutor::getMessageQueueThread() { } void JSCExecutor::onMessageReceived(int workerId, const std::string& json) { - Value rebornJSMsg = Value::fromJSON(m_context, String(json.c_str())); - JSValueRef args[] = { rebornJSMsg }; Object& worker = m_webWorkerJSObjs.at(workerId); Value onmessageValue = worker.getProperty("onmessage"); if (onmessageValue.isUndefined()) { return; } + + JSValueRef args[] = { JSCWebWorker::createMessageObject(m_context, json) }; onmessageValue.asObject().callAsFunction(1, args); m_flushImmediateCallback(flush(), true); diff --git a/ReactAndroid/src/main/jni/react/JSCWebWorker.cpp b/ReactAndroid/src/main/jni/react/JSCWebWorker.cpp index b385c1472..2357ddce4 100644 --- a/ReactAndroid/src/main/jni/react/JSCWebWorker.cpp +++ b/ReactAndroid/src/main/jni/react/JSCWebWorker.cpp @@ -53,8 +53,8 @@ void JSCWebWorker::postMessage(JSValueRef msg) { if (isFinished()) { return; } - Value rebornJSMsg = Value::fromJSON(context_, String(msgString.c_str())); - JSValueRef args[] = { rebornJSMsg }; + + JSValueRef args[] = { createMessageObject(context_, msgString) }; Value onmessageValue = Object::getGlobalObject(context_).getProperty("onmessage"); onmessageValue.asObject().callAsFunction(1, args); }); @@ -111,5 +111,13 @@ JSValueRef JSCWebWorker::nativePostMessage( return JSValueMakeUndefined(ctx); } +/*static*/ +Object JSCWebWorker::createMessageObject(JSContextRef context, const std::string& msgJson) { + Value rebornJSMsg = Value::fromJSON(context, String(msgJson.c_str())); + Object messageObject = Object::create(context); + messageObject.setProperty("data", rebornJSMsg); + return std::move(messageObject); +} + } } diff --git a/ReactAndroid/src/main/jni/react/JSCWebWorker.h b/ReactAndroid/src/main/jni/react/JSCWebWorker.h index b4a45ef97..5e4070d84 100644 --- a/ReactAndroid/src/main/jni/react/JSCWebWorker.h +++ b/ReactAndroid/src/main/jni/react/JSCWebWorker.h @@ -58,6 +58,8 @@ public: void postMessage(JSValueRef msg); void finish(); bool isFinished(); + + static Object createMessageObject(JSContextRef context, const std::string& msgData); private: void initJSVMAndLoadScript(); void postRunnableToEventLoop(std::function&& runnable); diff --git a/ReactAndroid/src/main/jni/react/Value.cpp b/ReactAndroid/src/main/jni/react/Value.cpp index 0acbc38c8..ca292c0de 100644 --- a/ReactAndroid/src/main/jni/react/Value.cpp +++ b/ReactAndroid/src/main/jni/react/Value.cpp @@ -58,6 +58,10 @@ Object Value::asObject() { return std::move(ret); } +Object::operator Value() const { + return Value(m_context, m_obj); +} + Value Object::callAsFunction(int nArgs, JSValueRef args[]) { JSValueRef exn; JSValueRef result = JSObjectCallAsFunction(m_context, m_obj, NULL, nArgs, args, &exn); @@ -68,7 +72,7 @@ Value Object::callAsFunction(int nArgs, JSValueRef args[]) { return Value(m_context, result); } -Value Object::getProperty(String propName) const { +Value Object::getProperty(const String& propName) const { JSValueRef exn; JSValueRef property = JSObjectGetProperty(m_context, m_obj, propName, &exn); if (!property) { @@ -82,4 +86,26 @@ Value Object::getProperty(const char *propName) const { return getProperty(String(propName)); } +void Object::setProperty(const String& propName, const Value& value) const { + JSValueRef exn = NULL; + JSObjectSetProperty(m_context, m_obj, propName, value, kJSPropertyAttributeNone, &exn); + if (exn) { + std::string exceptionText = Value(m_context, exn).toString().str(); + throwJSExecutionException("Failed to set property: %s", exceptionText.c_str()); + } +} + +void Object::setProperty(const char *propName, const Value& value) const { + setProperty(String(propName), value); +} + +/* static */ +Object Object::create(JSContextRef ctx) { + JSObjectRef newObj = JSObjectMake( + ctx, + NULL, // create instance of default object class + NULL); // no private data + return Object(ctx, newObj); +} + } } diff --git a/ReactAndroid/src/main/jni/react/Value.h b/ReactAndroid/src/main/jni/react/Value.h index 8a845ebfe..fb02fe50a 100644 --- a/ReactAndroid/src/main/jni/react/Value.h +++ b/ReactAndroid/src/main/jni/react/Value.h @@ -111,14 +111,18 @@ public: return m_obj; } + operator Value() const; + bool isFunction() const { return JSObjectIsFunction(m_context, m_obj); } Value callAsFunction(int nArgs, JSValueRef args[]); - Value getProperty(String propName) const; + Value getProperty(const String& propName) const; Value getProperty(const char *propName) const; + void setProperty(const String& propName, const Value& value) const; + void setProperty(const char *propName, const Value& value) const; void makeProtected() { if (!m_isProtected && m_obj) { @@ -132,6 +136,11 @@ public: return Object(ctx, globalObj); } + /** + * Creates an instance of the default object class. + */ + static Object create(JSContextRef ctx); + private: JSContextRef m_context; JSObjectRef m_obj;