Skip to content

Commit

Permalink
WebWorkers: Add APIs for working with JSObjectRef
Browse files Browse the repository at this point in the history
Reviewed By: lexs

Differential Revision: D2779267

fb-gh-sync-id: 5c5a49988a1d501f15e5033b2dd5b528d97d96ed
  • Loading branch information
astreet authored and facebook-github-bot-5 committed Dec 30, 2015
1 parent e75e861 commit a68f8f4
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 7 deletions.
2 changes: 2 additions & 0 deletions ReactAndroid/src/main/jni/react/JSCHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSObjectRef.h>

#define throwJSExecutionException(...) jni::throwNewJavaException("com/facebook/react/bridge/JSExecutionException", __VA_ARGS__)

namespace facebook {
namespace react {

Expand Down
51 changes: 45 additions & 6 deletions ReactAndroid/src/main/jni/react/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <jni/fbjni.h>
#include <fb/log.h>

#include "JSCHelpers.h"

namespace facebook {
namespace react {

Expand Down Expand Up @@ -37,17 +39,54 @@ std::string Value::toJSONString(unsigned indent) const {
if (stringToAdopt == nullptr) {
JSValueProtect(m_context, exn);
std::string exceptionText = Value(m_context, exn).toString().str();
jni::throwNewJavaException(
"java/lang/IllegalArgumentException",
"Exception creating JSON string: %s",
exceptionText.c_str());
throwJSExecutionException("Exception creating JSON string: %s", exceptionText.c_str());
}
return String::adopt(stringToAdopt).str();
}

/* static */
Value Value::fromJSON(JSContextRef& ctx, const String& json) {
return Value(ctx, JSValueMakeFromJSONString(ctx, json));
Value Value::fromJSON(JSContextRef ctx, const String& json) {
auto result = JSValueMakeFromJSONString(ctx, json);
if (!result) {
throwJSExecutionException("Failed to create String from JSON");
}
return Value(ctx, result);
}

Object Value::asObject() {
JSValueRef exn;
JSObjectRef jsObj = JSValueToObject(context(), m_value, &exn);
if (!jsObj) {
std::string exceptionText = Value(m_context, exn).toString().str();
throwJSExecutionException("Failed to convert to object: %s", exceptionText.c_str());
}
Object ret = Object(context(), jsObj);
m_value = nullptr;
return std::move(ret);
}

Value Object::callAsFunction(int nArgs, JSValueRef args[]) {
JSValueRef exn;
JSValueRef result = JSObjectCallAsFunction(m_context, m_obj, NULL, nArgs, args, &exn);
if (!result) {
std::string exceptionText = Value(m_context, exn).toString().str();
throwJSExecutionException("Exception calling JS function: %s", exceptionText.c_str());
}
return Value(m_context, result);
}

Value Object::getProperty(String propName) const {
JSValueRef exn;
JSValueRef property = JSObjectGetProperty(m_context, m_obj, propName, &exn);
if (!property) {
std::string exceptionText = Value(m_context, exn).toString().str();
throwJSExecutionException("Failed to get property: %s", exceptionText.c_str());
}
return Value(m_context, property);
}

Value Object::getProperty(const char *propName) const {
return getProperty(String(propName));
}

} }
62 changes: 61 additions & 1 deletion ReactAndroid/src/main/jni/react/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <memory>
#include <sstream>
#include <JavaScriptCore/JSObjectRef.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <JavaScriptCore/JSStringRef.h>
#include <JavaScriptCore/JSValueRef.h>
Expand All @@ -15,6 +16,7 @@
namespace facebook {
namespace react {

class Value;
class Context;

class String : public noncopyable {
Expand Down Expand Up @@ -84,6 +86,58 @@ class String : public noncopyable {
JSRetainPtr<JSStringRef> m_string;
};

class Object : public noncopyable {
public:
Object(JSContextRef context, JSObjectRef obj) :
m_context(context),
m_obj(obj)
{}

Object(Object&& other) :
m_context(other.m_context),
m_obj(other.m_obj),
m_isProtected(other.m_isProtected) {
other.m_obj = nullptr;
other.m_isProtected = false;
}

~Object() {
if (m_isProtected && m_obj) {
JSValueUnprotect(m_context, m_obj);
}
}

operator JSObjectRef() const {
return m_obj;
}

bool isFunction() const {
return JSObjectIsFunction(m_context, m_obj);
}

Value callAsFunction(int nArgs, JSValueRef args[]);

Value getProperty(String propName) const;
Value getProperty(const char *propName) const;

void makeProtected() {
if (!m_isProtected && m_obj) {
JSValueProtect(m_context, m_obj);
m_isProtected = true;
}
}

static Object getGlobalObject(JSContextRef ctx) {
auto globalObj = JSContextGetGlobalObject(ctx);
return Object(ctx, globalObj);
}

private:
JSContextRef m_context;
JSObjectRef m_obj;
bool m_isProtected = false;
};

class Value : public noncopyable {
public:
Value(JSContextRef context, JSValueRef value);
Expand All @@ -110,6 +164,10 @@ class Value : public noncopyable {
return JSValueIsNull(context(), m_value);
}

bool isUndefined() const {
return JSValueIsUndefined(context(), m_value);
}

double asNumber() const {
if (isNumber()) {
return JSValueToNumber(context(), m_value, nullptr);
Expand All @@ -130,6 +188,8 @@ class Value : public noncopyable {
return JSValueIsObject(context(), m_value);
}

Object asObject();

bool isString() const {
return JSValueIsString(context(), m_value);
}
Expand All @@ -139,7 +199,7 @@ class Value : public noncopyable {
}

std::string toJSONString(unsigned indent = 0) const;
static Value fromJSON(JSContextRef& ctx, const String& json);
static Value fromJSON(JSContextRef ctx, const String& json);
protected:
JSContextRef context() const;
JSContextRef m_context;
Expand Down

0 comments on commit a68f8f4

Please sign in to comment.