blob: f9f8410f65efd94cf4fea0346353eeec77d83506 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "js_action.h"
#include "weex_env.h"
std::map<JSObjectRef, JSAction::jsFunction *>
JSAction::jsFunction::objMap = std::map<JSObjectRef, JSAction::jsFunction *>();
std::mutex JSAction::jsFunction::mutex;
std::map<std::string, JSAction::jsFunction *>
JSAction::functionMap = std::map<std::string, JSAction::jsFunction *>();
void JSAction::EvaluateScript(std::string js) {
JSValueRef exception = nullptr;
JSEvaluateScript(m_ContextRef,
JSStringCreateWithUTF8CString(js.c_str()),
nullptr,
nullptr,
0,
&exception);
if (exception != nullptr) {
if (JSValueIsNull(m_ContextRef, exception)) {
return;
}
JSStringRef str = JSValueToStringCopy(m_ContextRef, exception, nullptr);
std::string result;
size_t max_bytes = JSStringGetMaximumUTF8CStringSize(str);
result.resize(max_bytes);
size_t bytes_written = JSStringGetUTF8CString(str, &(result)[0], max_bytes);
if (max_bytes == 0) {
return;
}
result.resize(bytes_written - 1);
JSStringRelease(str);
std::unique_ptr<BackToWeexCoreQueue> &ptr = WeexEnv::getEnv()->m_back_to_weex_core_thread;
if (ptr == nullptr || ptr.get() == nullptr) {
return;
}
BackToWeexCoreQueue *bwq = ptr.get();
BackToWeexCoreQueue::IPCTask
*t = new BackToWeexCoreQueue::IPCTask(IPCProxyMsg::JSACTIONCALLBACK);
auto temp = std::to_string(this->m_ctxContainer);
t->addParams(temp.c_str(), temp.length());
temp = std::to_string(static_cast<int32_t >(JSCALLBACK::EXCEPTION));
t->addParams(temp.c_str(), temp.length());
t->addParams(result.c_str(), result.length());
bwq->addTask(t);
}
}
void JSAction::BindFunction(std::string name) {
JSAction::jsFunction *&pJsFunction = functionMap[name];
if (pJsFunction != nullptr) {
delete pJsFunction;
}
JSAction::jsFunction
*pFunction = new JSAction::jsFunction(name, m_ContextRef, this->m_ctxContainer);
functionMap[name] = pFunction;
}
JSValueRef JSAction::jsFunction::StaticFunctionCallback(JSContextRef ctx,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
JSValueRef const *arguments,
JSValueRef *exception) {
jsFunction *&pFunction = objMap[function];
if (pFunction == nullptr) {
return nullptr;
}
std::unique_ptr<BackToWeexCoreQueue> &ptr = WeexEnv::getEnv()->m_back_to_weex_core_thread;
if (ptr == nullptr || ptr.get() == nullptr) {
return nullptr;
}
BackToWeexCoreQueue *bwq = ptr.get();
const char *name = pFunction->m_name_.c_str();
std::string result;
if (argumentCount > 0) {
JSValueRef const pValue = arguments[argumentCount - 1];
if (JSValueIsString(ctx, pValue)) {
JSStringRef pString = JSValueToStringCopy(ctx, pValue, nullptr);
size_t max_bytes = JSStringGetMaximumUTF8CStringSize(pString);
result.resize(max_bytes);
size_t bytes_written = JSStringGetUTF8CString(pString, &(result)[0], max_bytes);
if (max_bytes == 0) {
return nullptr;
}
result.resize(bytes_written - 1);
JSStringRelease(pString);
}
}
auto
*t = new BackToWeexCoreQueue::IPCTask(IPCProxyMsg::JSACTIONCALLBACK);
auto temp = std::to_string(pFunction->m_ctxContainer);
t->addParams(temp.c_str(), temp.length());
temp = std::to_string(static_cast<int32_t >(JSCALLBACK::INVOKE));
t->addParams(temp.c_str(), temp.length());
t->addParams(name, strlen(name));
t->addParams(result.c_str(), result.size());
LOGD_TAG("JSEngine","CallBack %s -> %s", name,result.c_str());
auto future = std::unique_ptr<BackToWeexCoreQueue::Future>(
new BackToWeexCoreQueue::Future());
t->set_future(future.get());
bwq->addTask(t);
std::unique_ptr<IPCResult> ipc_ret = future.get()->waitResult();
if (ipc_ret->getType() == IPCType::CHARARRAY) {
const char *string = ipc_ret.get()->getByteArrayContent();
if (string == nullptr) {
return JSValueMakeNull(ctx);
}
JSStringRef pJSString = JSStringCreateWithUTF8CString(string);
return JSValueMakeString(ctx, pJSString);
}
return JSValueMakeNull(ctx);
}
JSObjectRef JSAction::jsFunction::StaticConstructorCallback(JSContextRef ctx,
JSObjectRef constructor,
size_t argumentCount,
JSValueRef const *arguments,
JSValueRef *exception) {
return nullptr;
}
bool JSAction::jsFunction::StaticHasInstanceCallback(JSContextRef ctx,
JSObjectRef constructor,
JSValueRef possibleInstance,
JSValueRef *exception) {
return false;
}
void JSAction::jsFunction::StaticFinalizeCallback(JSObjectRef object) {
}
JSValueRef JSAction::jsFunction::GetProperty(JSContextRef ctx,
JSObjectRef object,
JSStringRef propertyName,
JSValueRef *exception) {
std::string result;
size_t max_bytes = JSStringGetMaximumUTF8CStringSize(propertyName);
result.resize(max_bytes);
size_t bytes_written = JSStringGetUTF8CString(propertyName, &(result)[0], max_bytes);
if (max_bytes == 0) {
return nullptr;
}
result.resize(bytes_written - 1);
if (JSObjectHasProperty(ctx, object, propertyName)) {
return JSObjectGetProperty(ctx, object, propertyName, nullptr);
}
return JSValueMakeUndefined(ctx);
}
namespace {
std::once_flag hostObjectClassOnceFlag;
JSClassRef hostObjectClass{};
} // namespace
JSAction::jsFunction::jsFunction(std::string name, JSContextRef ctx,
long ctxContainer) {
ctxRef = ctx;
m_ctxContainer = ctxContainer;
std::call_once(hostObjectClassOnceFlag, []() {
JSClassDefinition definition = kJSClassDefinitionEmpty;
definition.version = 0;
definition.finalize = StaticFinalizeCallback;
definition.callAsFunction = StaticFunctionCallback;
definition.callAsConstructor = StaticConstructorCallback;
definition.hasInstance = StaticHasInstanceCallback;
hostObjectClass = JSClassCreate(&definition);
});
m_name_ = name;
JSStringRef jssName = JSStringCreateWithUTF8CString(name.c_str());
objRef = JSObjectMake(ctx, hostObjectClass, jssName);
JSValueProtect(ctx, objRef);
JSObjectSetProperty(ctx, JSContextGetGlobalObject(ctx), jssName, objRef, 0,
nullptr);
mutex.lock();
objMap[objRef] = this;
mutex.unlock();
}
JSAction::jsFunction::~jsFunction() {
}