open source

This commit is contained in:
lvfulong
2020-11-11 16:17:13 +08:00
parent 4d989f3ecb
commit bc4ca748de
2441 changed files with 623057 additions and 2 deletions
@@ -0,0 +1,264 @@
#ifdef JS_V8
#include "JSArrayBuffer.h"
#include <util/JCMemorySurvey.h>
#include <util/Log.h>
#include "../JSInterface.h"
#include "JSCProxyTrnasfer.h"
namespace laya {
//TODO 这里没有考虑多线程的问题,如果js要支持多线程的话,需要修改。
struct JsStrBuff {
char* _buff;
int _len;
static std::vector<JsStrBuff> jsstrbuffs;
static int curIdx;
JsStrBuff() {
_buff = NULL;
_len = 0;
}
static JsStrBuff& getAData() {
if (JsStrBuff::curIdx >= (int)JsStrBuff::jsstrbuffs.size()) {
JsStrBuff::jsstrbuffs.push_back(JsStrBuff());
JsStrBuff::curIdx++;
return JsStrBuff::jsstrbuffs.back();
}
else {
return JsStrBuff::jsstrbuffs[JsStrBuff::curIdx++];
}
}
};
std::vector<JsStrBuff> JsStrBuff::jsstrbuffs;
int JsStrBuff::curIdx = 0;
//
void resetJsStrBuf() {
JsStrBuff::curIdx = 0;
}
char* JsCharToC(Local<Value> p_vl) {
int len = 0;
Local<String> str = p_vl->ToString();
len = str->Utf8Length();
if (len <= 0)
return "";
JsStrBuff& curdata = JsStrBuff::getAData();
char*& tocharBuf = curdata._buff;
int& tocharBufLen = curdata._len;
//tocharBuf= new char[len + 1];
if (len > tocharBufLen) {
tocharBufLen = len;
if (tocharBuf != NULL)
delete[] tocharBuf;
tocharBuf = new char[len+1];
}
else {
//如果占用空间太大,也要重新分配
if (tocharBufLen > 1024 ) {
tocharBufLen = len;
if (tocharBuf != NULL)
delete[] tocharBuf;
tocharBuf = new char[len+1];
}
}
str->WriteUtf8(tocharBuf);
return tocharBuf;
}
}
namespace laya{
ArrayBufferAllocator::ArrayBufferAllocator() {
}
ArrayBufferAllocator::~ArrayBufferAllocator() {
}
void* ArrayBufferAllocator::Allocate(size_t length) {
char* pRet = new char[length];
memset(pRet,0,length);
return pRet;
}
void* ArrayBufferAllocator::AllocateUninitialized(size_t length){
char* pRet = new char[length];
return pRet;
};
void ArrayBufferAllocator::Free(void* data, size_t length)
{
if (data != NULL || length > 0)
{
delete[]((char*)data);
}
else
{
LOGI("ArrayBufferAllocator::Free data=%d length=%d",(intptr_t)data, length);
}
}
ArrayBufferAllocator* ArrayBufferAllocator::getInstance(){
return new ArrayBufferAllocator();
}
v8::Local<v8::ArrayBuffer> createJSAB(char* pData, int len) {
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), len);
v8::ArrayBuffer::Contents contents = ab->GetContents();// ab->Externalize();
char* pPtr = (char*)contents.Data();
memcpy(pPtr, pData, len);
//Externalize 以后会减去内存占用,导致不能正确GC,所以再给加回来。不知道管理ArrayBuffer的正确方法是什么。
//v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(len);
return ab;
}
v8::Local<v8::ArrayBuffer> createJSABAligned(char* pData, int len) {
int asz = (len + 3) & 0xfffffffc;
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), asz);
v8::ArrayBuffer::Contents contents = ab->GetContents();// ab->Externalize();
char* pPtr = (char*)contents.Data();
memcpy(pPtr, pData, len);
//ArrayBuffer 自己已经初始化为0了
//Externalize 以后会减去内存占用,导致不能正确GC,所以再给加回来。不知道管理ArrayBuffer的正确方法是什么。
//v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(asz);
return ab;
}
bool extractJSAB(JsValue jsval, char*& data, int& len) {
v8::Local<v8::ArrayBuffer> ab;
if (jsval->IsArrayBufferView()) {
v8::Local<v8::ArrayBufferView> abv = v8::Local<v8::ArrayBufferView>::Cast(jsval);
len = abv->ByteLength();
ab = abv->Buffer();
v8::ArrayBuffer::Contents contents = ab->GetContents();
//len = contents.ByteLength(); 这种情况下,用view的长度,因为可能多个view公用一个大buffer
data = (char*)contents.Data()+abv->ByteOffset();
}
else if (jsval->IsArrayBuffer()) {
ab = v8::Local<v8::ArrayBuffer>::Cast(jsval);
v8::ArrayBuffer::Contents contents = ab->GetContents();
len = contents.ByteLength();
data = (char*)contents.Data();
}
else {
data = NULL;
len = 0;
return false;
}
/*
if (ab->IsExternal()) {
v8::ArrayBuffer::Contents contents = ab->GetContents();
len = contents.ByteLength();
data = (char*)contents.Data();
}
else {
v8::ArrayBuffer::Contents contents = ab->Externalize();
len = contents.ByteLength();
v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(len);
data = (char*)contents.Data();
}
*/
return true;
}
void __JSRun::ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
v8::HandleScope handle_scope(isolate);
v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = ToCString(exception);
v8::Handle<v8::Message> message = try_catch->Message();
static char errInfo[2048];
int curpos = 0;
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
int off = snprintf(errInfo, sizeof(errInfo), "%s\n", exception_string);
//通知全局错误处理脚本
std::string kBuf = "if(conch.onerror){conch.onerror('";
kBuf += UrlEncode(exception_string);
kBuf += "','undefined','undefined','undefined','";
kBuf += UrlEncode(exception_string);
kBuf += "');};";
__JSRun::Run(kBuf.c_str());
}
else {
auto ctx = isolate->GetCurrentContext();
v8::String::Utf8Value fnstr (message->GetScriptResourceName());
const char* filename_string = ToCString(fnstr);
v8::MaybeLocal<String> source_line_maybe = message->GetSourceLine(ctx);
v8::String::Utf8Value srclinestr(source_line_maybe.ToLocalChecked());
const char* sourceline_string = ToCString(srclinestr);
int linenum = message->GetLineNumber(ctx).FromJust();
int start = message->GetStartColumn(ctx).FromMaybe(0);
int end = message->GetEndColumn(ctx).FromMaybe(0);
v8::ScriptOrigin origin = message->GetScriptOrigin();
int lineoff = origin.ResourceLineOffset()->Value();
int startcol = origin.ResourceColumnOffset()->Value();
if (start > startcol) {
start -= startcol;
end -= startcol;
}
//错误行可能非常长,只取一部分
char errLineSrc[128];
if (strlen(sourceline_string) > 128) {
int startoff = start > 50 ? (start - 50) : 0;
start -= startoff;
end -= startoff;
if (end >= 128)end = 127;
memcpy(errLineSrc, sourceline_string+startoff, 128);
sourceline_string = errLineSrc;
}
curpos += snprintf(errInfo, sizeof(errInfo), "%s:%i:\n%s\n%s\n",
filename_string,
linenum,
exception_string,
sourceline_string);
//打印具体哪一行,哪一列
if (curpos < sizeof(errInfo)) {
int st = curpos;
int srclen = snprintf(errInfo + curpos, sizeof(errInfo) - curpos, "%s\n", sourceline_string);
curpos += srclen;
if (curpos < sizeof(errInfo)) {
for (int si = 0; si < srclen; si++) {
char& c = errInfo[st+si];
if (c != ' ' && c != '\t' && c != '\r')c = ' ';
if (si >= start && si <= end)c = '^';
}
}
}
curpos += snprintf(errInfo + curpos,sizeof(errInfo)-curpos, "\n");
v8::String::Utf8Value stack_trace(try_catch->StackTrace());
if (stack_trace.length() > 0) {
const char* stack_trace_string = ToCString(stack_trace);
if (curpos < sizeof(errInfo)) {
curpos += snprintf(errInfo + curpos,sizeof(errInfo)-curpos, "%s", stack_trace_string);
}
}
//通知全局错误处理脚本
std::string kBuf = "if(conch.onerror){conch.onerror('";
kBuf += UrlEncode(exception_string);
kBuf += "','";
kBuf += UrlEncode(filename_string);
kBuf += "','";
//kBuf += std::to_string(linenum);
std::ostringstream os;
os << linenum;
kBuf += os.str();
kBuf += "','";
kBuf += "undefined";
kBuf += "','";
kBuf += UrlEncode(errInfo);
kBuf += "');};";
__JSRun::Run(kBuf.c_str());
}
if (gbAlertException)
JSAlert(errInfo);
else {
LOGE("==JSERROR:\n%s", errInfo);
}
}
}
#endif
@@ -0,0 +1,38 @@
#ifndef _JS_ARRAYBUFFER_H_
#define _JS_ARRAYBUFFER_H_
#include <v8.h>
#include <vector>
/*
如果有c这边的ArrayBufferView引用这个ArrayBuffer的话,需要增加引用计数,不能直接删除
*/
namespace laya{
//这个要在v8线程外分配和释放,因为v8析构的时候会调用这个对象提供的 Free 接口
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
public:
ArrayBufferAllocator();
~ArrayBufferAllocator();
virtual void* Allocate(size_t length) ;
virtual void* AllocateUninitialized(size_t length);
virtual void Free(void* data, size_t length);
//这个函数没有意义,v8本身会都释放掉 Heap::FreeDeadArrayBuffers
//void FreeAllAlive();//释放所有的还没有释放的ArrayBuffer
static ArrayBufferAllocator* getInstance();
//int _testGetID(void* pdata);
//int getAliveBufferNum() {
// return m_vAliveBuffer.size();
//}
protected:
//std::vector<char*> m_vAliveBuffer;
};
v8::Local<v8::ArrayBuffer> createJSAB(char* pData, int len);
v8::Local<v8::ArrayBuffer> createJSABAligned(char* pData, int len);
bool extractJSAB(v8::Local<v8::Value> ab, char*& data, int& len);
}
#endif
@@ -0,0 +1,69 @@
//
// JSCProxyTLS.h
// jsc_test
//
// Created by 蒋 宇彤 on 13-11-25.
// Copyright (c) 2013年 蒋 宇彤. All rights reserved.
//
#ifndef jsc_test_JSCProxyTLS_h
#define jsc_test_JSCProxyTLS_h
#include <v8.h>
#include <string>
#include <util/JCCommonMethod.h>
#include <util/Log.h>
#include <sstream>
namespace laya{
extern void JSAlert(const char* p_sBuffer);
class __JsThrow {
public:
static void Throw( const char *p_pszInfo ) {
v8::Isolate::GetCurrent()->ThrowException(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), (0==p_pszInfo)?"unknown error":p_pszInfo));
}
};
extern bool gbAlertException;
class __JSRun {
public:
// Extracts a C string from a V8 Utf8Value.
static const char* ToCString(const v8::String::Utf8Value& value) {
return *value ? *value : "<string conversion failed>";
}
static void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch);
static bool Run( const char *p_pszScript ) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
v8::TryCatch try_catch(isolate);
v8::Handle<v8::String> source = v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), p_pszScript);
v8::Handle<v8::Script> script = v8::Script::Compile(source);
if( script.IsEmpty() ){
//打印编译错误信息
printf("---Compile script error---\n");
ReportException(isolate, &try_catch);
return false;
}
v8::Handle<v8::Value> res = script->Run();
if( !res.IsEmpty() && !res->IsUndefined() )
{
v8::String::Utf8Value ascii(res);
printf("run result: [%s]\n", *ascii);
}
if( try_catch.HasCaught()){
printf("---run script error---\n");
ReportException(isolate, &try_catch);
}
return true;
}
};
}
#endif
@@ -0,0 +1,402 @@
//
// JSCProxyTrnasfer.h
// jsc_test
//
// Created by 蒋 宇彤 on 13-11-25.
// Copyright (c) 2013年 蒋 宇彤. All rights reserved.
//
#ifndef jsc_test_JSCProxyTrnasfer_h
#define jsc_test_JSCProxyTrnasfer_h
#include <v8.h>
#include <string>
#include <vector>
#include "JSArrayBuffer.h"
//#include "JsBinder.h"
using namespace v8;
namespace laya{
//为了能快速返回js的字符串,现在转字符串的函数使用了通用buffer,
//为了能同时返回多个buffer指针,就用了一个vector,为了避免vector一直增加,内存泄露
//就用了这个函数。具体看代码。
void resetJsStrBuf();
template<class T>
Local<Object> createJsObjAttachCObj(T* cobj, bool weak);
template <typename T> class __TransferToCpp{public:
static T ToCpp( Local<Value> p_vl ){
// 这是很危险的
if( !p_vl.IsEmpty() && p_vl->IsObject() ){
return static_cast<T>((p_vl.As<Object>())->GetAlignedPointerFromInternalField(0));
}else{
return (T)0;
}
}
//问题:如果是对象的话,当请求 T或者T* 认为是相同的
static bool is(Local<Value> p_vl) {
if (!p_vl->IsObject())
return false;
Local<Object> obj = p_vl.As<Object>();
if (obj->InternalFieldCount() < 2)
return false;
void* pdt = obj->GetAlignedPointerFromInternalField(1);
if( pdt == &T::JSCLSINFO) {
return true;
}
return false;
}
};
//不知道怎么区分对象和对象指针,先硬写一个
template <typename T> class __TransferToCpp<T*> {
public:
static T* ToCpp(Local<Value> p_vl) {
// 这是很危险的
if (!p_vl.IsEmpty() && p_vl->IsObject()) {
Local<Object> obj = p_vl.As<Object>();
return static_cast<T*>(obj->GetAlignedPointerFromInternalField(0));
}
else {
return (T*)0;
}
}
//问题:如果是对象的话,当请求 T或者T* 认为是相同的
static bool is(Local<Value> p_vl) {
if (!p_vl->IsObject())
return false;
Local<Object> obj = p_vl.As<Object>();
void* pdt = obj->GetAlignedPointerFromInternalField(1);
if (pdt == &T::JSCLSINFO) {
return true;
}
return false;
}
};
template <> class __TransferToCpp<int32_t> {
public:
static int32_t ToCpp(Local<Value> p_vl) { return p_vl->Int32Value(); }
static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
};
template <> class __TransferToCpp<int64_t> {
public:
static int64_t ToCpp(Local<Value> p_vl) { return p_vl->IntegerValue(); }
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
};
template <> class __TransferToCpp<uint32_t> {
public:
static uint32_t ToCpp(Local<Value> p_vl) { return p_vl->Uint32Value(); }
static bool is(Local<Value> p_vl) { return p_vl->IsUint32(); }
};
template <> class __TransferToCpp<uint64_t> {
public:
static uint64_t ToCpp(Local<Value> p_vl) { return (uint64_t)p_vl->IntegerValue(); }
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
};
// template <> class __TransferToCpp<int>{public:
// static int ToCpp( Local<Value> p_vl ){return p_vl->Int32Value();}
// static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
//};
//template <> class __TransferToCpp<short> {public:
// static short ToCpp(Local<Value> p_vl) { return p_vl->Int32Value(); }
// static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
//};
// template <> class __TransferToCpp<unsigned int> {public:
// static unsigned int ToCpp( Local<Value> p_vl ){return p_vl->Uint32Value();}
// static bool is(Local<Value> p_vl) { return p_vl->IsUint32(); }
//};
// template <> class __TransferToCpp<long>{public:
// static long ToCpp( Local<Value> p_vl ){return p_vl->Int32Value();}
// static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
//};
// template <> class __TransferToCpp<unsigned long>{public:
// static unsigned long ToCpp( Local<Value> p_vl ){return p_vl->Uint32Value();}
// static bool is(Local<Value> p_vl) { return p_vl->IsUint32(); }
//};
template <> class __TransferToCpp<bool>{public:
static bool ToCpp( Local<Value> p_vl ){return p_vl->BooleanValue();}
static bool is(Local<Value> p_vl) { return p_vl->IsBoolean(); }
};
template <> class __TransferToCpp<float>{public:
static float ToCpp( Local<Value> p_vl ){return (float)p_vl->NumberValue();}
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
};
template <> class __TransferToCpp<double>{public:
static double ToCpp( Local<Value> p_vl ){return p_vl->NumberValue();}
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
};
// template <> class __TransferToCpp<long long>{public:
// static long long ToCpp( Local<Value> p_vl ){return p_vl->IntegerValue();}
// static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
//};
// template <> class __TransferToCpp<unsigned long long>{public:
// static unsigned long long ToCpp( Local<Value> p_vl ){return (unsigned long long)p_vl->IntegerValue();}
// static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
//};
template <> class __TransferToCpp<Local<Value>>{public:
static Local<Value> ToCpp(Local<Value> p_vl) { return p_vl; }
static bool is(Local<Value> p_vl) { return true; }
};
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制。
//这个函数必须配合 resetJsStrBuf 函数使用。
//例如
// char* p1 = JsCharToC(args[0]);
// char* p2 = JsCharToC(args[1]);
// use(p1,p2);
// resetJsStrBuf();
char* JsCharToC(Local<Value> p_vl);
class transToCharPtr {
public:
static char *ToCpp1(Local<Value> p_vl) {
String::Utf8Value utf8str(p_vl->ToString());
//return *utf8str;
//下面有泄露
char *pRet = 0;
size_t len;
if (0 != *utf8str && 0 != (len = strlen(*utf8str))){
pRet = new char[len + 1];
memcpy(pRet, *utf8str, len + 1);
}
return pRet;
}
static std::string ToCppStd(Local<Value> p_vl) {
String::Utf8Value utf8str(p_vl->ToString());
return std::string(*utf8str);
}
};
template <> class __TransferToCpp<char *> {public:
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
static char* ToCpp(Local<Value> p_vl) { return JsCharToC(p_vl); }
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
};
template <> class __TransferToCpp<const char *> {public:
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
static const char* ToCpp(Local<Value> p_vl) { return (const char*)JsCharToC(p_vl); }
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
};
template <> class __TransferToCpp<unsigned char *> {public:
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
static unsigned char* ToCpp(Local<Value> p_vl) { return (unsigned char*)JsCharToC(p_vl); }
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
};
template <> class __TransferToCpp<const unsigned char *> {public:
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
static const unsigned char* ToCpp(Local<Value> p_vl) { return (const unsigned char*)JsCharToC(p_vl); }
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
};
//template<> class __TransferToCpp<laya::JSArrayBuffer*>{public:
// static bool is(Local<Value> p_vl) { return p_vl->IsArrayBuffer() || p_vl->IsArrayBufferView(); }
// static laya::JSArrayBuffer* ToCpp(Local<Value> p_vl) { return laya::JSArrayBuffer::fromeJSObj(p_vl); };
//};
template <typename T> class __TransferToJs{
public:static Handle<Value> ToJs(T* p_vl) {
return laya::createJsObjAttachCObj<T>(p_vl,true);
}
};
//为什么不直接把没有参数作为void?
template <> class __TransferToJs<void>
{public:static Handle<Value> ToJs( int p_vl )
{
if(0==p_vl)
return Undefined(Isolate::GetCurrent());
else
return Null(Isolate::GetCurrent());
}};
template <> class __TransferToJs<v8::Local<v8::Value>>{
public:static Handle<Value> ToJs(v8::Local<v8::Value> p_vl) { return p_vl; }
};
template <> class __TransferToJs<v8::Local<v8::Object> >
{
public:static Handle<Value> ToJs(v8::Local<v8::Object> p_vl) { return p_vl; }
};
template <> class __TransferToJs<bool>
{public:static Handle<Value> ToJs( bool p_vl ){return Boolean::New(Isolate::GetCurrent(),p_vl);}};
template <> class __TransferToJs<int>
{public:static Handle<Value> ToJs( int p_vl ){return Int32::New(Isolate::GetCurrent(), p_vl);}};
template <> class __TransferToJs<unsigned int>
{public:static Handle<Value> ToJs( unsigned int p_vl ){return Uint32::New(Isolate::GetCurrent(), p_vl);}};
template <> class __TransferToJs<long unsigned int>
{
public:static Handle<Value> ToJs(long unsigned int p_vl) { return Number::New(Isolate::GetCurrent(), p_vl); }
};
template <> class __TransferToJs<float>
{public:static Handle<Value> ToJs( float p_vl ){return Number::New(Isolate::GetCurrent(), p_vl);}};
template <> class __TransferToJs<double>
{public:static Handle<Value> ToJs( double p_vl ){return Number::New(Isolate::GetCurrent(), p_vl);}};
template <> class __TransferToJs<long long>
{
public:
static Handle<Value> ToJs( long long p_vl )
{
return Number::New(Isolate::GetCurrent(), (double)p_vl);
}
static Handle<Value> ToJsDate( long long p_vl )
{
return Date::New(Isolate::GetCurrent(), (double)p_vl );
}
};
template <> class __TransferToJs<long>
{
public:
static Handle<Value> ToJs( long p_vl )
{
return Number::New(Isolate::GetCurrent(), (double)p_vl);
}
static Handle<Value> ToJsDate( long p_vl )
{
return Date::New(Isolate::GetCurrent(), (double)p_vl );
}
};
template <> class __TransferToJs<unsigned long long>
{
public:
static Handle<Value> ToJs( unsigned long long p_vl )
{
return Number::New(Isolate::GetCurrent(), (double)p_vl);
}
static Handle<Value> ToJsDate( unsigned long long p_vl )
{
return Date::New(Isolate::GetCurrent(), (double)p_vl );
}
};
template <> class __TransferToJs<char *>
{public:static Handle<Value> ToJs( char *p_vl ){if(p_vl==0) p_vl=(char*)""; return String::NewFromUtf8(Isolate::GetCurrent(),p_vl);}};
template <> class __TransferToJs<const char *>
{public:static Handle<Value> ToJs( const char *p_vl ){if(p_vl==0) p_vl=(const char *)""; return String::NewFromUtf8(Isolate::GetCurrent(),p_vl);}};
template <> class __TransferToJs<unsigned char *>
{public:static Handle<Value> ToJs( const unsigned char*p_vl ){if(p_vl==0) p_vl=(const unsigned char*)""; return String::NewFromUtf8(Isolate::GetCurrent(),(const char *)p_vl);}};
template <> class __TransferToJs<const unsigned char *>
{public:static Handle<Value> ToJs( const unsigned char *p_vl ){if(p_vl==0) p_vl=(const unsigned char *)""; return String::NewFromUtf8(Isolate::GetCurrent(),(const char *)p_vl);}};
template <> class __TransferToJs<std::string>
{public:static Handle<Value> ToJs( std::string p_vl ){return String::NewFromUtf8(Isolate::GetCurrent(), p_vl.c_str());}};
template <> class __TransferToJs<std::string&> {
public:static Handle<Value> ToJs(std::string& p_vl) { return String::NewFromUtf8(Isolate::GetCurrent(), p_vl.c_str()); }
};
//template <> class __TransferToJs<laya::JSArrayBuffer*>
//{public:static Handle<Value> ToJs( laya::JSArrayBuffer* p_vl ){return p_vl->toLocal();}};
template <typename T> class __JsArray{
public:
static Handle<Value> ToJsArray(const std::vector<T*>& p_v1)
{
int size=p_v1.size();
if(0==size)
{
Handle<Array> __array = Array::New(Isolate::GetCurrent(), 0);
return __array;
}
else
{
Handle<Array> __array = Array::New(Isolate::GetCurrent(), size);
for(int i=0;i<size;i++)
{
//__array->Set(i, __JSCProxy_class<T>::GetInstance()->TransferObjPtrToJS(p_v1.at(i)));
__array->Set(i, __TransferToJs<T>::ToJs(p_v1.at(i)));
}
return __array;
}
}
static Handle<Value> ToJsArray(const std::vector<T>& p_v1)
{
int size = p_v1.size();
if (0 == size)
{
Handle<Array> __array = Array::New(Isolate::GetCurrent(), 0);
return __array;
}
else
{
Handle<Array> __array = Array::New(Isolate::GetCurrent(), size);
for (int i = 0; i<size; i++)
{
//__array->Set(i, __JSCProxy_class<T>::GetInstance()->TransferObjPtrToJS(p_v1.at(i)));
__array->Set(i, __TransferToJs<T>::ToJs(p_v1.at(i)));
}
return __array;
}
}
};
class __JsByteArray
{
public:
static Handle<Value> ToJsByteArray( const unsigned char *p_vl, int p_iSize )
{
if( 0 == p_vl || p_iSize <= 0 )
{
return Null(Isolate::GetCurrent());
}
else
{
Handle<Array> __array = Array::New(Isolate::GetCurrent(), p_iSize);
for(int i=0;i<p_iSize;++i)
{
__array->Set( i, Int32::New(Isolate::GetCurrent(), p_vl[i]) );
}
return __array;
}
}
};
template <typename T> class __TransferToJs<std::vector<T*> >
{
public:static Handle<Value> ToJs( const std::vector<T*>& p_vl )
{
return __JsArray<T>::ToJsArray(p_vl);
}
};
template <typename T> class __TransferToJs<std::vector<T> >
{
public:static Handle<Value> ToJs(const std::vector<T>& p_vl)
{
return __JsArray<T>::ToJsArray(p_vl);
}
};
}
#endif
@@ -0,0 +1,93 @@
//
// JSCProxyType.h
// jsc_test
//
// Created by 蒋 宇彤 on 13-12-1.
// Copyright (c) 2013年 蒋 宇彤. All rights reserved.
//
#ifndef jsc_test_JSCProxyType_h
#define jsc_test_JSCProxyType_h
#include <v8.h>
#include "JSCProxyTLS.h"
namespace laya{
typedef enum {
__VT_void = 0,
__VT_string,
__VT_bool,
__VT_int,
__VT_long,
__VT_float,
__VT_double,
__VT_longlong,
__VT_ArrayBuffer,
__VT_object,
} __ValueType;
template <class _Key> struct __InferType
{__ValueType iType;__InferType(){iType=__VT_object;}};
template<> struct __InferType<void>
{__ValueType iType;__InferType(){iType=__VT_void;}};
template<> struct __InferType<bool>
{__ValueType iType;__InferType(){iType=__VT_bool;}};
template<> struct __InferType<char *>
{__ValueType iType;__InferType(){iType=__VT_string;}};
template<> struct __InferType<const char *>
{__ValueType iType;__InferType(){iType=__VT_string;}};
template<> struct __InferType<unsigned char *>
{__ValueType iType;__InferType(){iType=__VT_string;}};
template<> struct __InferType<const unsigned char *>
{__ValueType iType;__InferType(){iType=__VT_string;}};
template<> struct __InferType<int>
{__ValueType iType;__InferType(){iType=__VT_int;}};
template<> struct __InferType<unsigned int>
{__ValueType iType;__InferType(){iType=__VT_int;}};
template<> struct __InferType<long>
{__ValueType iType;__InferType(){iType=__VT_long;}};
template<> struct __InferType<unsigned long>
{__ValueType iType;__InferType(){iType=__VT_long;}};
template<> struct __InferType<float>
{__ValueType iType;__InferType(){iType=__VT_float;}};
template<> struct __InferType<double>
{__ValueType iType;__InferType(){iType=__VT_double;}};
template<> struct __InferType<long long>
{__ValueType iType;__InferType(){iType=__VT_longlong;}};
template<> struct __InferType<unsigned long long>
{__ValueType iType;__InferType(){iType=__VT_longlong;}};
class __CheckClassType
{
public:
template <typename T>
static bool IsTypeOf( v8::Local<v8::Value> p_Obj )
{
if( p_Obj.IsEmpty() || !p_Obj->IsObject() )
return false;
else {
v8::Local<v8::Object> obj = p_Obj.As<v8::Object>();
void* pdt = v8::Local<v8::External>::Cast(obj->GetInternalField(1))->Value();
return pdt == &T::JSCLSINFO;
}
}
};
} // namespace __JSCProxy
#endif
@@ -0,0 +1,248 @@
/**
@file JSEnv.cpp
@brief
@author James
@version 1.0
@date 2018_8_23
*/
#ifdef JS_V8
#include "JSEnv.h"
#include <v8-profiler.h>
#include "../../v8debug/debug-agent.h"
#include "util/Log.h"
#include "JSCProxyTLS.h"
#ifdef WIN32
#include <windows.h>
#include <process.h>
#endif
//#define V8PROFILE
namespace laya
{
v8::Persistent<v8::Context> Javascript::m_DebugMessageContext;
const char* ToCString(const v8::String::Utf8Value& value)
{
return *value ? *value : "<string conversion failed>";
}
class LayaHandleScope :public v8::HandleScope
{
public:
LayaHandleScope(v8::Isolate* piso)
{
HandleScope::Initialize(piso);
}
~LayaHandleScope()
{
}
public:
void Initialize(v8::Isolate* isolate)
{
HandleScope::Initialize(isolate);
}
};
Javascript::Javascript()
{
m_pIsolate = NULL;
m_pPlatform = NULL;
m_pScope = NULL;
m_pHandleScope = NULL;
m_pV8Locker = NULL;
m_pABAlloc = NULL;
m_nListenPort = 0;
}
void Javascript::init(int nPort)
{
if (!m_pPlatform)
{
m_pPlatform = v8::platform::CreateDefaultPlatform();
v8::V8::InitializePlatform(m_pPlatform);
}
v8::V8::Initialize();
m_nListenPort = 0;
if(nPort > 0 && nPort <0xFFFF )
{
m_nListenPort = nPort;
}
}
void Javascript::uninit()
{
//不能在v8线程
return;
if (0 != m_pIsolate)
{
m_pIsolate->Dispose();
m_pIsolate = 0;
ArrayBufferAllocator* pABAlloc = ArrayBufferAllocator::getInstance();
//pABAlloc->FreeAllAlive();
delete pABAlloc;
}
}
void Javascript::initJSEngine()
{
v8::Isolate::CreateParams create_params;
m_pABAlloc = ArrayBufferAllocator::getInstance();
create_params.array_buffer_allocator = m_pABAlloc;
m_pIsolate = v8::Isolate::New(create_params);
static char* flags[] =
{
"--expose_gc",
"--allow-natives-syntax",//导出内部的%函数
//"--trace-gc-verbose",
//"--use-strict",
//"--harmony",
//"--print-bytecode", //
//"--print-bytecode-filter errf1"
//"--trace-ignition-codegen",
//"--debug-code",
//"--trace-opt",
//"--trace-deopt",
//"--prof",
//"--code-comments",
};
for (auto f : flags)
{
v8::V8::SetFlagsFromString(f, strlen(f));
}
#ifdef V8PROFILE
v8::V8::SetFlagsFromString("--prof", 6);
char* pSingleLogFile = "--no-logfile_per_isolate";
v8::V8::SetFlagsFromString(pSingleLogFile, strlen(pSingleLogFile));
#ifdef ANDROID
char* profFile = "--logfile /sdcard/lr2perf/v8.log";
#elif WIN32
char* profFile = "--logfile d:/temp/v8.log";
#endif
v8::V8::SetFlagsFromString(profFile, strlen(profFile));
#endif
//m_pLocker = new v8::Locker(m_pIsolate);
//这个{}是为了能让 Scope起作用
m_pScope = new v8::Isolate::Scope(m_pIsolate);
m_pHandleScope = (v8::HandleScope*)malloc(sizeof(v8::HandleScope));
new (m_pHandleScope) LayaHandleScope(m_pIsolate);
v8::Handle<v8::ObjectTemplate> pGlobalTemplate = v8::ObjectTemplate::New(m_pIsolate);
v8::Local<v8::Context> context = v8::Context::New(m_pIsolate, NULL, pGlobalTemplate, v8::Handle<v8::Value>());
context->Enter();
//v8::CpuProfiler* pCpuProf = m_pIsolate->GetCpuProfiler();
//pCpuProf->StartCpuProfiling(v8::String::New(""));
//pCpuProf->StopCpuProfiling(v8::String::New(""));
if (m_nListenPort > 0)
{
{
std::unique_lock<std::recursive_mutex> __guard(m_Lock);
if (m_DebugMessageContext.IsEmpty())
{
m_DebugMessageContext.Reset(m_pIsolate, v8::Local<v8::Context>::New(m_pIsolate, context));
}
}
}
}
void Javascript::uninitJSEngine()
{
//当js线程要结束的时候,关闭调试,否则调试器客户端在线程结束后再发送调试事件,会导致非法。
if (m_nListenPort > 0)
{
//v8::Debug::DisableAgent();
}
if (!m_DebugMessageContext.IsEmpty())
{
m_DebugMessageContext.Reset();
}
//应该调用退出,但是context在scope中,先不退出了,发现也没有内存泄漏
//context->Enter();
delete m_pHandleScope;
m_pHandleScope = NULL;
delete m_pScope;
m_pScope = NULL;
m_pIsolate->Dispose();
delete m_pABAlloc;
}
void Javascript::run(const char* sSource, std::function<void(void)> preRunFunc)
{
}
void Javascript::run(const char* sSource)
{
}
void Javascript::run(voidfun func, void* pdata)
{
v8::TryCatch try_catch(m_pIsolate);
func(pdata);
if (try_catch.HasCaught())
{
v8::String::Utf8Value exceptioninfo(try_catch.Exception());
printf("Exception info [%s]\n", *exceptioninfo);
}
}
//------------------------------------------------------------------------------
JSV8Worker::JSV8Worker()
{
}
JSV8Worker::~JSV8Worker()
{
}
void JSV8Worker::_defRunLoop()
{
#ifdef WIN32
{
DWORD thid = GetCurrentThreadId();
SetNameInternal(thid, m_strName.c_str());
//threadInfoLog("start thread:%s,%d", m_strName.c_str(), thid);
}
#elif ANDROID
{
//threadInfoLog("start thread:%s,%ld", m_strName.c_str(), gettidv1());
}
#endif
//开始事件
JCEventEmitter::evtPtr startEvt(new JCEventBase);
startEvt->m_nID = JCWorkerThread::Event_threadStart;
emit(startEvt);
JCWorkerThread::runObj task;
while (!m_bStop)
{
v8::TryCatch trycatch(v8::Isolate::GetCurrent());
if (!m_funcLoop)
{
//现在的waitdata返回false不再表示要退出。事件唤醒流程
if (m_ThreadTasks.WaitData(&task))
task();
}
else
{
//固定循环流程
runQueue();
if (!m_funcLoop())
{
break;
}
}
if (trycatch.HasCaught())
{
v8::Isolate* piso = v8::Isolate::GetCurrent();
if( piso )__JSRun::ReportException(piso, &trycatch);
}
}
//退出事件
JCEventEmitter::evtPtr stopEvt(new JCEventBase);
stopEvt->m_nID = JCWorkerThread::Event_threadStop;
emit(stopEvt);
}
void call_JSThread__defRunLoop(void* pdata)
{
JSV8Worker* pthis=(JSV8Worker*)pdata;
pthis->_defRunLoop();
}
void JSV8Worker::_runLoop()
{
m_pJS->initJSEngine();
m_pJS->run(call_JSThread__defRunLoop,this);
m_pJS->uninitJSEngine();
}
}
#endif
//------------------------------------------------------------------------------
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,354 @@
/**
@file JSEnv.h
@brief
@author James
@version 1.0
@date 2018_8_23
*/
#ifndef __JSEnv_H__
#define __JSEnv_H__
#include <v8.h>
#include <libplatform/libplatform.h>
#include <thread>
#include <mutex>
#include <misc/JCWorkerThread.h>
#include <util/ListNode.h>
#include "JSArrayBuffer.h"
#include <util/Log.h>
#include "JSCProxyTLS.h"
namespace laya
{
void JSPrint( const char* p_sBuffer );
void JSAlert( const char* p_sBuffer );
void evalJS( const char* p_sSource );
const char* ToCString(const v8::String::Utf8Value& value);
class Javascript
{
public:
typedef std::recursive_mutex _MutexType;
typedef void(*voidfun)(void* data);
Javascript();
void init(int nPort);
//在init之后,并且在js线程的情况下,可以添加js导出
//执行一段脚本。并立即退出。
void run(const char* sSource );
//preRunFunc 是在执行脚本之前先执行的函数,例如可以做导出对象
void run(const char* sSource, std::function<void(void)> preRunFunc );
//执行一个函数。并立即退出
void run(voidfun func,void* pdata);
//不能在v8线程,在js退出后,可以进行js对象的清理
void uninit();
void initJSEngine();
void uninitJSEngine();
public:
static v8::Persistent<v8::Context> m_DebugMessageContext;
v8::Isolate* m_pIsolate;
v8::Platform* m_pPlatform;
v8::Isolate::Scope* m_pScope;
v8::HandleScope* m_pHandleScope;
v8::Locker* m_pV8Locker;
ArrayBufferAllocator* m_pABAlloc;
_MutexType m_Lock;
int m_nListenPort;
};
class JSThreadInterface
{
public:
JSThreadInterface()
{
}
virtual ~JSThreadInterface()
{
}
virtual void post(std::function<void(void)> func) = 0;
virtual void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread=0) = 0;
virtual void start() = 0;
virtual void stop() = 0;
virtual void initialize(int nPort) = 0;
virtual void uninitialize() = 0;
virtual void setLoopFunc(std::function<bool(void)> func) = 0;
virtual void pushDbgFunc(std::function<void(void)> task) = 0;
virtual void runDbgFuncs() = 0;
virtual void waitAndRunDbgFuncs() = 0;
virtual bool hasDbgFuncs() = 0;
virtual JCWorkerThread* getWorker() = 0;
virtual void run(Javascript::voidfun func,void* pData) = 0;
virtual void clearFunc() = 0;
};
class JSV8Worker : public JCWorkerThread
{
public:
JSV8Worker();
~JSV8Worker();
//因为要trycatch,所以只好再抄一份了
virtual void _defRunLoop();
virtual void _runLoop();
public:
Javascript* m_pJS;
};
//把Javascript对象放到一个单独的线程中执行。
class JSMulThread: public JSThreadInterface
{
public:
JSMulThread()
{
m_kWorker.setThreadName("JavaScript Main");
m_kWorker.m_pJS = &m_kJS;
}
~JSMulThread()
{
//uninitialize();
}
void post(std::function<void(void)> func)
{
m_kWorker.post(func);
}
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread=0)
{
m_kWorker.on(nEvent, func, (JCWorkerThread*)pInThread);
}
void start()
{
m_kWorker.start();
}
void stop()
{
m_kWorker.stop();
}
void initialize(int nPort)
{
m_kJS.init(nPort);
}
void uninitialize()
{
m_kJS.uninit();
}
void setLoopFunc(std::function<bool(void)> func)
{
m_kWorker.setLoopFunc(func);
}
void pushDbgFunc(std::function<void(void)> task)
{
m_DbgFuncLock.lock();
m_DbgFunction.push_back(task);
m_DbgFuncLock.unlock();
}
void runDbgFuncs()
{
m_DbgFuncLock.lock();
for (std::function<void(void)>& task : m_DbgFunction)
{
task();
}
m_DbgFunction.clear();
m_DbgFuncLock.unlock();
}
void waitAndRunDbgFuncs()
{
m_DbgFuncLock.lock();
m_DbgFuncLock.unlock();
}
bool hasDbgFuncs()
{
bool bRet = false;
m_DbgFuncLock.lock();
bRet = m_DbgFunction.size() > 0;
m_DbgFuncLock.unlock();
return bRet;
}
JCWorkerThread* getWorker()
{
return &m_kWorker;
}
void run(Javascript::voidfun func, void* pData)
{
}
void clearFunc()
{
}
protected:
std::vector<std::function<void(void)>> m_DbgFunction; //调试函数
std::mutex m_DbgFuncLock;
JSV8Worker m_kWorker;
Javascript m_kJS;
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//把Javascript对象放到一个单独的线程中执行。
class JSSingleThread : public JSThreadInterface
{
public:
JSSingleThread()
{
}
~JSSingleThread()
{
//uninitialize();
}
void post(std::function<void(void)> func)
{
m_kQueueLock.lock();
m_vFuncQueue.push_back(func);
m_kQueueLock.unlock();
}
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread = 0)
{
switch (nEvent)
{
case JCWorkerThread::Event_threadStart:
m_kStartFunc.func = func;
m_kStartFunc.bDel = false;
break;
case JCWorkerThread::Event_threadStop:
m_kStopFunc.func = func;
m_kStopFunc.bDel = false;
break;
default:
LOGE("JSSingleThread on() event type error");
break;
}
}
void start()
{
m_kStartFunc.func(NULL);
}
void stop()
{
m_kStopFunc.func(NULL);
}
void initialize(int nPort)
{
clearFunc();
m_kJS.init(nPort);
m_kJS.initJSEngine();
}
void uninitialize()
{
clearFunc();
m_kJS.uninit();
m_kJS.uninitJSEngine();
}
void setLoopFunc(std::function<bool(void)> func)
{
LOGE("JSSingleThread setLoopFunc error,You can't call this function on V8 Engine");
}
void pushDbgFunc(std::function<void(void)> task)
{
m_DbgFuncLock.lock();
m_DbgFunction.push_back(task);
m_DbgFuncLock.unlock();
}
void runDbgFuncs()
{
m_DbgFuncLock.lock();
for (std::function<void(void)>& task : m_DbgFunction)
{
task();
}
m_DbgFunction.clear();
m_DbgFuncLock.unlock();
}
void waitAndRunDbgFuncs()
{
m_DbgFuncLock.lock();
m_DbgFuncLock.unlock();
}
bool hasDbgFuncs()
{
bool bRet = false;
m_DbgFuncLock.lock();
bRet = m_DbgFunction.size() > 0;
m_DbgFuncLock.unlock();
return bRet;
}
JCWorkerThread* getWorker()
{
return NULL;
}
void run(Javascript::voidfun func, void* pData)
{
v8::TryCatch try_catch(m_kJS.m_pIsolate);
runFunQueue();
if (pData)func(pData);
if (try_catch.HasCaught())
{
__JSRun::ReportException(m_kJS.m_pIsolate, &try_catch);
}
}
void clearFunc()
{
m_kQueueLock.lock();
m_vFuncQueue.clear();
m_kQueueLock.unlock();
}
public:
void runFunQueue()
{
std::vector<std::function<void(void)>> vWorkQueue;
m_kQueueLock.lock();
std::swap(vWorkQueue, m_vFuncQueue);
m_kQueueLock.unlock();
for (int i = 0; i < (int)vWorkQueue.size(); i++)
{
vWorkQueue[i]();
}
}
protected:
std::vector<std::function<void(void)>> m_DbgFunction; //调试函数
std::mutex m_DbgFuncLock;
Javascript m_kJS;
JCEventEmitter::EvtHandlerPack m_kStartFunc;
JCEventEmitter::EvtHandlerPack m_kStopFunc;
std::vector<std::function<void(void)>> m_vFuncQueue; //需要在此线程执行的函数的队列
std::mutex m_kQueueLock;
};
};
//------------------------------------------------------------------------------
#endif //__JSEnv_H__
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,169 @@
#ifdef JS_V8
#include "JsBinder.h"
#include "../JSInterface.h"
using namespace v8;
namespace laya {
thread_local JSClassMgr JSClassMgr::__Ins;
void imp_js2cfunc_common(const FunctionCallbackInfo<Value>& args) {
void* pExData = External::Cast(*args.Data())->Value();
Local<Object> pthis = args.This();
if (pthis->InternalFieldCount() > 1) {
JsObjClassInfo* id = (JsObjClassInfo*)Handle<External>::Cast(pthis->GetInternalField(1))->Value();
void *pObj = Handle<External>::Cast(pthis->GetInternalField(0))->Value();
int a = 0;
}
JSP_RUN_SCRIPT("printstack();");
throw - 1;//不能调到这里 //支持基本类型,或者Value
}
bool checkJSToCArgs(const FunctionCallbackInfo<Value>& args, int num) {
int len = args.Length();
if (len >= num)
return true;
static char buff[512];
/*算了,别alert了,log把
sprintf(buff, "alert('arguments number err: %d:%d');printstack();", num, len);
JSP_RUN_SCRIPT(buff);
throw - 1;//不能调到这里 //支持基本类型,或者Value
*/
sprintf(buff, "console.log('arguments number err: %d:%d');var e = new Error();console.log(e.stack);", num, len);
JSP_RUN_SCRIPT(buff);
return false;
}
Local<Function> createJSMethodRaw(FunctionCallback func, JsValue data) {
Isolate* pIso = Isolate::GetCurrent();
Local<FunctionTemplate> method = FunctionTemplate::New(pIso);
method->SetCallHandler(func, data);
return method->GetFunction();
}
JSObjBaseV8::JSObjBaseV8() {
mpRefArray = NULL;
mpCurJsArgs = NULL;
mpJsThis = NULL;
mnRefArrSize = 0;
mbWeakThis = true;
//放在构造里面,容易导致没有js环境而非法。还是往后放放吧。
mpJsIso = NULL;
//mpJsIso = Isolate::GetCurrent();
}
JSObjBaseV8::~JSObjBaseV8() {
if (!mbWeakThis) {
mpJsThis->Reset();
delete mpJsThis;
mpJsThis = NULL;
}
}
void JSObjBaseV8::destroyWeakCB(const WeakCallbackInfo<Persistent<Object> >& data) {
HandleScope __lHandleScope(Isolate::GetCurrent());
Persistent<Object> *pPersistentVal = data.GetParameter();
//Handle<Object> pNewIns = Local<Object>::New(Isolate::GetCurrent(), *pPersistentVal);
//T *ptr = (T *)Handle<External>::Cast(pNewIns->GetInternalField(0))->Value();
//delete ptr;
pPersistentVal->Reset();
delete pPersistentVal;
}
void JSObjBaseV8::destroyWeakRefArray(const WeakCallbackInfo<Persistent<Array> >& data) {
Persistent<Array>* pData = data.GetParameter();
//JSObjBaseV8* pObj = pData->pObj;
if (pData == NULL)
return;
//Isolate* piso = Isolate::GetCurrent();
//HandleScope __lHandleScope(piso);
/*
Local<Array> refArr = pData->Get(piso);
int sz = refArr->Length();
for (int i = 0; i < sz; i++) {
refArr->Delete(piso->GetCurrentContext(), i);
}
*/
pData->Reset();
delete pData;
}
void JSObjBaseV8::retainThis() {
//我觉得这个其实应该不用。
mRetainedThis.Reset(mpJsIso, mpJsThis->Get(mpJsIso));
}
void JSObjBaseV8::releaseThis() {
mRetainedThis.Reset();
}
void JSObjBaseV8::createJSObj() {
if (!mpJsIso)mpJsIso = Isolate::GetCurrent();
Local<Object> jsobj = Local<Object>::New(mpJsIso, Object::New(mpJsIso));
mpJsThis = new Persistent<Object>(mpJsIso, jsobj);
mbWeakThis = false;
createRefArray();
}
/*
void JSObjBaseV8::addRefHandle(JsObjHandle2* handle) {
handle->m_pObj = this;
handle->m_nID = mnRefArrSize++;
}
*/
//創建一個數組,用於保存引用的js對象。
void JSObjBaseV8::createRefArray() {
mpJsIso = Isolate::GetCurrent();
Local<Array> refarr = Array::New(mpJsIso, mnRefArrSize);
int le = refarr->Length();
Local<Object> jsthis = Local<Object>::New(mpJsIso, *mpJsThis);
//需要把它加到this的引用中,防止这个数组被删除掉。
jsthis->Set(Js_Str(mpJsIso, "__internal_refArray"), refarr);
//这个是为了访问方便。可能去掉更好。
mpRefArray = new Persistent<Array>(mpJsIso, refarr);
//由于自己有引用,所以不用再在回调中删掉了。
mpRefArray->SetWeak(mpRefArray, JSObjBaseV8::destroyWeakRefArray, v8::WeakCallbackType::kInternalFields);
}
void JSObjBaseV8::setRefObj(int idx, JsValue obj) {
if (!mpRefArray)
return;
if (mnRefArrSize <= idx)mnRefArrSize = idx + 1;
Local<Array> refArr = mpRefArray->Get(mpJsIso);
refArr->Set(idx, obj);
}
Local<Object> JSObjBaseV8::getRefObj(int idx) {
Local<Array> refArr = mpRefArray->Get(mpJsIso);
return refArr->Get(idx).As<Object>();
}
Persistent<Object>* JSObjBaseV8::weakHoldJsObj(Local<Object>& pobj) {
Persistent<Object>* pObj = new Persistent<Object>(mpJsIso, pobj);
pObj->SetWeak(pObj, destroyWeakCB, v8::WeakCallbackType::kInternalFields);
return pObj;
}
JsValue JSObjBaseV8::callJsFunc(JsFunction& func) {
int argc = 0;
Local<Value> argv[1];
return _callJsFunc(func, argc, argv);
}
bool JsObjHandle2::Empty() {
if (!m_pObj)
return true;
return m_pObj->getRefObj(m_nID).IsEmpty();
}
void JsObjHandle2::set(JsValue& v) {
if (m_pObj == NULL) {
LOGE("throw set jsvalue m_pObj==null ");
throw - 4;
}
m_pObj->setRefObj(m_nID, v);
}
}
#endif
File diff suppressed because it is too large Load Diff