■
JsValueRefはvoid* のtypedefなので、何者なのか掴みにくい。また、スタック上でない場所でキープする場合は、AddRefしなければならない。多分、GarvageCollectが働いた時に回収されてしまうのを避けるため。
そこで、CJsValueRefというラッパークラスを作ってみた。スクリプト上での型が分かっている場合に使える。
(少なくともWM_DESTROYのタイミングで、使用したすべてのCJsValueRefをReleaseして下さい。)
#include "stdafx.h"
#define _JSRT_
#include "ChakraCore.h"
#include
#include
#include
#include
#pragma comment (lib, "chakracore")
using namespace std;
class CJsValueRef
{
public:
CJsValueRef() :ref_(nullptr) {}
explicit CJsValueRef(JsValueRef ref);
CJsValueRef(const CJsValueRef& r);
~CJsValueRef() { Release(); }
CJsValueRef(int val);
CJsValueRef(double val);
CJsValueRef(LPCWSTR str);
CJsValueRef(bool bl);
CJsValueRef(const std::vector
CJsValueRef(const std::map
UINT AddRef();
UINT Release();
// Convert functions
std::vector
int ToInt() const;
double ToDouble() const;
std::wstring ToString() const;
std::map
bool ToBool() const;
bool empty() { return (ref_ == nullptr); }
CJsValueRef& operator=(const CJsValueRef& x);
private:
JsValueRef ref_;
};
int main()
{
JsRuntimeHandle runtime;
JsContextRef context;
JsValueRef result;
unsigned currentSourceContext = 0;
wstring script = L"(()=>{ var a = { 'tokyo':'03', 'yokohama':'045', 'oosaka':'06'}; return a;})()"; // <-- map
JsCreateRuntime(JsRuntimeAttributeNone, nullptr, &runtime);
// Create an execution context.
JsCreateContext(runtime, &context);
// Now set the execution context as being the current one on this thread.
JsSetCurrentContext(context);
// Run the script.
JsRunScript(script.c_str(), currentSourceContext++, L"", &result);
{
CJsValueRef x = result;
auto m = x.ToMap();
wcout << L'{';
for( auto& it : m )
{
wcout << it.first << L':' << it.second.ToString();
}
wcout << L'}' << endl;
// output is "{tokyo:03,yokohama:045,oosaka:06,}"
}
system("pause");
// Dispose runtime
JsSetCurrentContext(JS_INVALID_REFERENCE);
JsDisposeRuntime(runtime);
return 0;
}
///////////////////////////////////////////////////
CJsValueRef::CJsValueRef(JsValueRef ref)
{
ref_ = ref;
AddRef();
}
CJsValueRef::CJsValueRef(const CJsValueRef& r)
{
ref_ = r.ref_;
AddRef();
}
CJsValueRef::CJsValueRef(int val)
{
JsIntToNumber(val,&ref_);
//AddRef(); 不要
}
CJsValueRef::CJsValueRef(double val)
{
JsDoubleToNumber(val,&ref_);
//AddRef();
}
CJsValueRef::CJsValueRef(LPCWSTR str)
{
JsPointerToString(str,lstrlen(str), &ref_);
AddRef();
}
CJsValueRef::CJsValueRef(bool bl)
{
JsBoolToBoolean( bl, &ref_ );
//AddRef();
}
CJsValueRef::CJsValueRef(const std::vector
{
JsCreateArray( ar.size(), &ref_ );
AddRef();
int i = 0;
for( auto& it : ar )
{
JsValueRef index;
JsIntToNumber(i++, &index );
JsSetIndexedProperty( ref_, index, it.ref_ );
}
}
CJsValueRef::CJsValueRef( const std::map
{
JsCreateArray( m.size(), &ref_ );
AddRef();
JsValueRef jsobj;
JsConvertValueToObject(ref_, &jsobj );
JsValueRef xnm;
JsGetOwnPropertyNames( jsobj, &xnm );
int i = 0;
for( auto& it : m )
{
auto& key = it.first;
JsValueRef index;
JsIntToNumber(i++, &index);
JsValueRef ck;
JsPointerToString( key.c_str(),key.length(), &ck );
auto er = JsSetIndexedProperty(xnm, index, ck); // set xnm.
_ASSERT( er == JsNoError);
JsValueRef IndexedProperty;
er = JsGetIndexedProperty(xnm, index, &IndexedProperty);
_ASSERT( er == JsNoError);
er = JsSetIndexedProperty( jsobj, IndexedProperty, it.second.ref_ ); // set jsobj.
_ASSERT( er == JsNoError);
}
}
UINT CJsValueRef::AddRef()
{
UINT refcnt = 0;
JsAddRef(ref_, &refcnt);
return refcnt;
}
UINT CJsValueRef::Release()
{
UINT refcnt = 0;
if (ref_)
JsRelease(ref_, &refcnt);
ref_ = nullptr;
return refcnt;
}
CJsValueRef& CJsValueRef::operator=(const CJsValueRef& x)
{
if (this == &x)
return *this;
Release();
ref_ = x.ref_;
AddRef();
return *this;
}
std::vector
{
std::vector
JsValueRef jsobj;
if ( JsNoError == JsConvertValueToObject(ref_, &jsobj))
{
JsValueRef xnm;
JsGetOwnPropertyNames(jsobj, &xnm);
JsValueRef lengthName, lengthValue;
ret = JsGetPropertyIdFromName(L"length", &lengthName);
ret = JsGetProperty(xnm, lengthName, &lengthValue);
int count;
JsNumberToInt(lengthValue, &count);
if (count)
{
ar.resize(count - 1);
for (int i = 0; i < count - 1; i++)
{
JsValueRef index;
JsIntToNumber(i, &index);
JsValueRef IndexedProperty;
JsGetIndexedProperty(jsobj, index, &IndexedProperty);
ar[i] = CJsValueRef(IndexedProperty);
}
}
}
return ar;
}
bool CJsValueRef::ToBool() const
{
bool ret = false;
JsValueRef a;
JsConvertValueToBoolean(ref_,&a);
JsBooleanToBool(a,&ret);
return ret;
}
int CJsValueRef::ToInt() const
{
int ret = 0;
JsValueRef a;
JsConvertValueToNumber(ref_, &a);
JsNumberToInt(a, &ret);
return ret;
}
double CJsValueRef::ToDouble() const
{
double ret = 0;
JsValueRef a;
JsConvertValueToNumber(ref_, &a);
JsNumberToDouble(a, &ret);
return ret;
}
std::wstring CJsValueRef::ToString() const
{
JsValueRef a;
JsConvertValueToString(ref_, &a);
const wchar_t* cb; size_t len;
JsStringToPointer(a, &cb, &len);
return std::wstring(cb, len);
}
std::map
{
std::map
JsValueRef jsobj;
if ( JsNoError == JsConvertValueToObject(ref_, &jsobj))
{
JsValueRef xnm;
JsGetOwnPropertyNames(jsobj, &xnm);
JsValueRef lengthName, lengthValue;
ret = JsGetPropertyIdFromName(L"length", &lengthName);
ret = JsGetProperty(xnm, lengthName, &lengthValue);
int count;
JsNumberToInt(lengthValue, &count);
std::vector
for (int i = 0; i < count; i++)
{
JsValueRef index;
JsIntToNumber(i, &index);
JsValueRef IndexedProperty;
ret = JsGetIndexedProperty(xnm, index, &IndexedProperty);
JsValueRef itemref;
JsConvertValueToString(IndexedProperty, &itemref);
WCHAR* cb; UINT len;
JsStringToPointer(itemref, (const wchar_t**) &cb, &len);
si.push_back(cb);
}
for (int i = 0; i < count; i++)
{
JsValueRef index;
JsPointerToString(si[i].c_str(), si[i].length(), &index);
JsValueRef IndexedProperty;
JsGetIndexedProperty(jsobj, index, &IndexedProperty);
map[ si[i] ] = CJsValueRef(IndexedProperty);
}
}
return map;
}