blob: f1182a0ad299d5ec7825c3c57ff4d5e3f5622ab6 [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.
*/
//
// Created by Darin on 11/02/2018.
//
#include "android/jsengine/weex_jsc_utils.h"
#include <iostream>
#include <fstream>
#include "android/jsengine/object/weex_global_object.h"
#include "android/jsengine/object/weex_env.h"
#include "core/bridge/script_bridge.h"
//extern WEEX_CORE_JS_API_FUNCTIONS *weex_core_js_api_functions;
using namespace JSC;
void printLogOnFileWithNameS(const char * name, const char *log) {
std::string string("/data/data/com.alibaba.weex/");
string.append(name);
std::ofstream mcfile;
mcfile.open(string.c_str(), std::ios::app);
mcfile << log << std::endl;
mcfile.close();
}
String jString2String(const uint16_t *str, size_t length) {
UChar *dst;
String s = String::createUninitialized(length, dst);
memcpy(dst, str, length * sizeof(UChar));
return s;
}
String weexString2String(const WeexString *weexString) {
if (weexString != nullptr) {
return jString2String(weexString->content, weexString->length);
}
return String("");
}
String char2String(const char *string) {
if (string == nullptr)
return String::fromUTF8("");
return String::fromUTF8(string);
}
std::unique_ptr<char[]> newCharString(const char *str, size_t length) {
auto count = length + 1;
std::unique_ptr<char[]> buffer(new char[count]);
if (buffer == nullptr)
return nullptr;
char *result = reinterpret_cast<char *>(buffer.get());
if (result == nullptr)
return nullptr;
memset(result, 0, count);
memcpy(result, str, length);
result[length] = '\0';
return buffer;
}
std::unique_ptr<char[]> getCharJSONStringFromState(ExecState *state, int argument) {
if (argument >= state->argumentCount()) {
return nullptr;
}
JSValue val = state->argument(argument);
VM &vm = state->vm();
if (val.isObject()) {
VM &vm = state->vm();
auto scope = DECLARE_CATCH_SCOPE(vm);
String str = JSONStringify(state, val, 0);
if (UNLIKELY(scope.exception())) {
scope.clearException();
return nullptr;
}
CString data = str.utf8();
return newCharString(data.data(), data.length());
} else {
return nullptr;
}
}
std::unique_ptr<char[]> getCharOrJSONStringFromState(ExecState *state, int argument) {
if (argument >= state->argumentCount()) {
return nullptr;
}
JSValue val = state->argument(argument);
if (val.isString() || val.isNumber()) {
String str(val.toWTFString(state));
CString data = str.utf8();
return newCharString(data.data(), data.length());
} else if (val.isObject()) {
VM &vm = state->vm();
auto scope = DECLARE_CATCH_SCOPE(vm);
String str = JSONStringify(state, val, 0);
if (UNLIKELY(scope.exception())) {
scope.clearException();
return nullptr;
}
CString data = str.utf8();
return newCharString(data.data(), data.length());
} else {
return nullptr;
}
}
void getWsonOrJsonArgsFromState(ExecState *state, int argument, Args& args){
bool useWson = WeexEnv::getEnv()->useWson();
if(useWson){
if (argument >= state->argumentCount()) {
args.setWson((wson_buffer*)nullptr);
return;
}
JSValue val = state->argument(argument);
wson_buffer* buffer = wson::toWson(state, val);
args.setWson(buffer);
return;
}else{
if (argument >= state->argumentCount()) {
String str("");
args.setString(str);
return;
}
JSValue val = state->argument(argument);
if(val.isString()){
String str = val.toWTFString(state);
args.setString(str);
return;
}else if(val.isObject()){
VM &vm = state->vm();
auto scope = DECLARE_CATCH_SCOPE(vm);
String str = JSONStringify(state, val, 0);
args.setString(str);
return;
}
}
String str("");
args.setString(str);
return;
}
void getStringArgsFromState(ExecState *state, int argument,Args& args){
if (argument >= state->argumentCount()) {
String str("");
args.setString(str);
return;
}
JSValue val = state->argument(argument);
String str = val.toWTFString(state);
args.setString(str);
return;
}
void getWsonArgsFromState(ExecState *state, int argument, Args& args){
if (argument >= state->argumentCount()) {
args.setWson((wson_buffer*)nullptr);
return;
}
JSValue val = state->argument(argument);
wson_buffer* buffer = wson::toWson(state, val);
args.setWson(buffer);
return;
}
void getJSONArgsFromState(ExecState *state, int argument, Args& args){
JSValue val = state->argument(argument);
if(val.isString()){
String str = val.toWTFString(state);
args.setString(str);
return;
}else if(val.isObject()){
VM &vm = state->vm();
auto scope = DECLARE_CATCH_SCOPE(vm);
String str = JSONStringify(state, val, 0);
args.setString(str);
return;
}
String str("");
args.setString(str);
return;
}
void addObjectArgsToIPC(IPCSerializer *serializer, Args& args){
if(args.getType() == ARGS_TYPE_WSON){
wson_buffer* buffer = args.wson;
if(buffer != nullptr && (((char*)buffer->data)[0] != WSON_NULL_TYPE) ){
serializer->add((const char*)buffer->data, buffer->position);
}else{
serializer->addJSUndefined();
}
}else {
String str = args.json;
CString data = str.utf8();
serializer->add(data.data(), data.length());
}
}
void addStringArgsToIPC(IPCSerializer *serializer, Args& args){
if(args.json.length() > 0){
String str = args.json;
CString data = str.utf8();
serializer->add(data.data(), data.length());
}else{
serializer->addJSUndefined();
}
}
std::unique_ptr<char[]> getCharStringFromState(ExecState *state, int argument) {
JSValue val = state->argument(argument);
String s = val.toWTFString(state);
return newCharString(s.utf8().data(), s.length());
}
void getArgumentAsCString(IPCSerializer *serializer, ExecState *state, int argument) {
JSValue val = state->argument(argument);
String s = val.toWTFString(state);
serializer->add(s.utf8().data(), s.length());
}
void addString(IPCSerializer *serializer, const String &s) {
if (s.is8Bit()) {
CString data = s.utf8();
const char *cstr = data.data();
size_t length = data.length();
Vector<UChar, 1024> buffer(length);
UChar *p = buffer.data();
bool sourceIsAllASCII;
if (WTF::Unicode::conversionOK ==
WTF::Unicode::convertUTF8ToUTF16(&cstr, cstr + length, &p, p + length, &sourceIsAllASCII)) {
serializer->add(buffer.data(), std::distance(buffer.data(), p));
} else {
uint16_t tmp = 0;
serializer->add(&tmp, 0);
}
} else {
serializer->add(s.characters16(), s.length());
}
}
void getArgumentAsJString(IPCSerializer *serializer, ExecState *state, int argument) {
JSValue val = state->argument(argument);
String s = val.toWTFString(state);
addString(serializer, s);
}
void getArgumentAsJByteArrayJSON(IPCSerializer *serializer, ExecState *state, int argument) {
jbyteArray ba = nullptr;
if (argument >= state->argumentCount()) {
serializer->addJSUndefined();
return;
}
JSValue val = state->argument(argument);
VM &vm = state->vm();
if (val.isObject()) {
auto scope = DECLARE_CATCH_SCOPE(vm);
String str = JSONStringify(state, val, 0);
JSC::VM &vm = state->vm();
if (UNLIKELY(scope.exception())) {
scope.clearException();
serializer->addJSUndefined();
return;
}
CString data = str.utf8();
serializer->add(data.data(), data.length());
}
}
WeexByteArray *getArgumentAsWeexByteArrayJSON(ExecState *state, int argument) {
if (argument >= state->argumentCount()) {
return nullptr;
}
JSValue val = state->argument(argument);
VM &vm = state->vm();
if (val.isObject()) {
auto scope = DECLARE_CATCH_SCOPE(vm);
String str = JSONStringify(state, val, 0);
JSC::VM &vm = state->vm();
if (UNLIKELY(scope.exception())) {
scope.clearException();
return nullptr;
}
CString data = str.utf8();
//serializer->add(data.data(), data.length());
return genWeexByteArraySS(data.data(), data.length());
}
return nullptr;
}
WeexString *genWeexStringSS(const uint16_t *str, size_t length) {
size_t byteSize = length * sizeof(uint16_t);
auto *string = (WeexString *) malloc(byteSize + sizeof(WeexString));
if (string == nullptr)
return nullptr;
memset(string, 0, byteSize + sizeof(WeexString));
string->length = length;
memcpy(string->content, str, byteSize);
return string;
}
WeexByteArray *genWeexByteArraySS(const char *str, size_t strLen) {
auto *ret = (WeexByteArray *) malloc(strLen + sizeof(WeexByteArray));
if (ret == nullptr)
return nullptr;
memset(ret, 0, strLen + sizeof(WeexByteArray));
ret->length = strLen;
memcpy(ret->content, str, strLen);
ret->content[strLen] = '\0';
return const_cast<WeexByteArray *> (ret);
}
JSValue jString2JSValue(ExecState *state, const uint16_t *str, size_t length) {
String s = jString2String(str, length);
if (s.isEmpty()) {
return jsEmptyString(&state->vm());
} else if (s.length() == 1) {
return jsSingleCharacterString(&state->vm(), s[0]);
}
return jsNontrivialString(&state->vm(), WTFMove(s));
}
JSValue String2JSValue(ExecState *state, String s) {
if (s.isEmpty()) {
return jsEmptyString(&state->vm());
} else if (s.length() == 1) {
return jsSingleCharacterString(&state->vm(), s[0]);
}
return jsNontrivialString(&state->vm(), WTFMove(s));
}
JSValue parseToObject(ExecState *state, const String &data) {
VM &vm = state->vm();
auto scope = DECLARE_CATCH_SCOPE(vm);
JSValue ret = JSONParse(state, data);
if (UNLIKELY(scope.exception())) {
scope.clearException();
return jsUndefined();
}
if (!ret)
return jsUndefined();
return ret;
}
void getArgumentAsJByteArray(IPCSerializer *serializer, ExecState *state, int argument) {
jbyteArray ba = nullptr;
if (argument >= state->argumentCount()) {
serializer->addJSUndefined();
return;
}
JSValue val = state->argument(argument);
if (val.isString()) {
String str(val.toWTFString(state));
CString data = str.utf8();
serializer->add(data.data(), data.length());
} else {
getArgumentAsJByteArrayJSON(serializer, state, argument);
}
}
void freeInitFrameworkParams(std::vector<INIT_FRAMEWORK_PARAMS *> &params) {
for (auto &param : params) {
free(param->type);
free(param->value);
free(param);
}
}
void freeParams(std::vector<VALUE_WITH_TYPE *> &params) {
for (auto &param : params) {
if (param->type == ParamsType::STRING ||
param->type == ParamsType::JSONSTRING) {
free(param->value.string);
}
if (param->type == ParamsType::BYTEARRAY) {
free(param->value.byteArray);
}
free(param);
}
}
void FillVectorOfInitFramework(std::vector<INIT_FRAMEWORK_PARAMS *> &params,
IPCArguments *arguments, size_t start,
size_t end) {
for (size_t i = start; i < end; i += 2) {
if (arguments->getType(i) != IPCType::BYTEARRAY) {
continue;
}
if (arguments->getType(1 + i) != IPCType::BYTEARRAY) {
continue;
}
const IPCByteArray *ba = arguments->getByteArray(1 + i);
const IPCByteArray *ba_type = arguments->getByteArray(i);
auto init_framework_params =
(INIT_FRAMEWORK_PARAMS *) malloc(sizeof(INIT_FRAMEWORK_PARAMS));
if (init_framework_params == nullptr) {
break;
}
memset(init_framework_params, 0, sizeof(INIT_FRAMEWORK_PARAMS));
init_framework_params->type = IPCByteArrayToWeexByteArray(ba_type);
init_framework_params->value = IPCByteArrayToWeexByteArray(ba);
params.push_back(init_framework_params);
}
}
void initHeapTimer() {
HeapTimer::startTimerThread();
}
void deinitHeapTimer() {
HeapTimer::stopTimerThread();
}
void markupStateInternally() {
}
void doUpdateGlobalSwitchConfig(const char *config) {
if (!config) {
return;
}
LOGE("doUpdateGlobalSwitchConfig %s", config);
if (strstr(config, "wson_off") != NULL) {
WeexEnv::getEnv()->setUseWson(false);
} else {
WeexEnv::getEnv()->setUseWson(true);
}
}
String exceptionToString(JSGlobalObject *globalObject, JSValue exception) {
StringBuilder sb;
VM &vm = globalObject->vm();
auto scope = DECLARE_CATCH_SCOPE(vm);
#define CHECK_EXCEPTION() \
do { \
if (scope.exception()) { \
scope.clearException(); \
return String(); \
} \
} while (false)
sb.append(String::format("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data()));
Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
CHECK_EXCEPTION();
Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
CHECK_EXCEPTION();
Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
CHECK_EXCEPTION();
Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
CHECK_EXCEPTION();
JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
CHECK_EXCEPTION();
JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
CHECK_EXCEPTION();
JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
CHECK_EXCEPTION();
JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
CHECK_EXCEPTION();
if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
&& (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
sb.append(String::format(
"at %s:%s\n",
fileNameValue.toWTFString(globalObject->globalExec()).utf8().data(),
lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data()));
}
if (!stackValue.isUndefinedOrNull())
sb.append(String::format("%s\n", stackValue.toWTFString(globalObject->globalExec()).utf8().data()));
#undef CHECK_EXCEPTION
return sb.toString();
}
void setJSFVersion(WeexGlobalObject *globalObject) {
VM &vm = globalObject->vm();
PropertyName getJSFMVersionProperty(Identifier::fromString(&vm, "getJSFMVersion"));
ExecState *state = globalObject->globalExec();
JSValue getJSFMVersionFunction = globalObject->get(state, getJSFMVersionProperty);
MarkedArgumentBuffer args;
CallData callData;
CallType callType = getCallData(getJSFMVersionFunction, callData);
NakedPtr<Exception> returnedException;
JSValue version = call(globalObject->globalExec(), getJSFMVersionFunction, callType, callData, globalObject, args,
returnedException);
if (returnedException) {
ReportException(globalObject, returnedException.get(), "", "");
}
String str = version.toWTFString(state);
CString data = str.utf8();
globalObject->js_bridge()->core_side()->SetJSVersion(data.data());
}
void ReportException(JSGlobalObject *_globalObject, Exception *exception, const char *instanceid,
const char *func) {
String exceptionInfo = exceptionToString(_globalObject, exception->value());
CString data = exceptionInfo.utf8();
auto *globalObject = static_cast<WeexGlobalObject *>(_globalObject);
globalObject->js_bridge()->core_side()->ReportException(instanceid, func, data.data());
}
uint64_t microTime() {
struct timeval tv;
gettimeofday(&tv, nullptr);
return (((uint64_t) tv.tv_sec) * MICROSEC + tv.tv_usec);
}
int __atomic_inc(volatile int *ptr) {
return __sync_fetch_and_add(ptr,1);
}
static int taskIdGenerator = 0;
int genTaskId(){
return __atomic_inc(&taskIdGenerator);
}
/**
* this function is to execute a section of JavaScript content.
*/
bool ExecuteJavaScript(JSGlobalObject *globalObject,
const String &source,
const String &url,
bool report_exceptions,
const char *func,
const char *instanceId) {
SourceOrigin sourceOrigin(String::fromUTF8("(weex)"));
NakedPtr<Exception> evaluationException;
JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, sourceOrigin, url), JSValue(),
evaluationException);
if (report_exceptions && evaluationException) {
ReportException(globalObject, evaluationException.get(), instanceId, func);
return false;
}
if (evaluationException)
return false;
globalObject->vm().drainMicrotasks();
return true;
}
char *getCharFromUniquePtr(std::unique_ptr<char[]> str) {
return str == nullptr ? nullptr : str.get();
}
WeexByteArray *IPCByteArrayToWeexByteArray(const IPCByteArray *byteArray) {
return genWeexByteArraySS(byteArray->content, byteArray->length);
}
namespace WEEXICU {
unique_fd::unique_fd(int fd)
: m_fd(fd) {
}
unique_fd::~unique_fd() {
close(m_fd);
}
int unique_fd::get() const {
return m_fd;
}
}