SpiderMonkeyの学習
20838 ワード
ルール:
js論理コードで使用されるjsvalタイプの計算結果と渡される行パラメータは、RootedValueタイプ、RootedObject、JSSString、Numberまたはその他のタイプの値がRootedValueタイプの変数に保存されます.
jsonはRootedObjectタイプ配列でもRootedObjectタイプ用JS_IsArrayObjectは配列配列配列長がJS_を通過するか否かを判定するGetArrayLength取得要素JS_を介してGetElement取得
js to c++ value.isNumber(),JS::ToNumber() isObject(),JS_ValueToObject() v.isString(); JSString *tmp =JS::ToString(cx, v); JSStringWrapper str(tmp); *ret = str.get(); jsonタイプ値を読み込みます.
c++to js obj JS_NewObject JS_DefineProperty OBJECT_TO_JSVAL Array JS_NewArrayObject JS_SetElement OBJECT_TO_JSVAL int32_to_jsval std_string_to_jsvalはjsonタイプ値を作成します.
js配列を作成する
グローバル関数c++変調js js変調c++
c++クラスのコールバック関数
js関数はc++に渡され、関数コールバックに使用されます.
テスト1
テスト2
テスト3
テスト4
テスト5
テスト6
テスト7
テスト8
js論理コードで使用されるjsvalタイプの計算結果と渡される行パラメータは、RootedValueタイプ、RootedObject、JSSString、Numberまたはその他のタイプの値がRootedValueタイプの変数に保存されます.
jsonはRootedObjectタイプ配列でもRootedObjectタイプ用JS_IsArrayObjectは配列配列配列長がJS_を通過するか否かを判定するGetArrayLength取得要素JS_を介してGetElement取得
js to c++ value.isNumber(),JS::ToNumber() isObject(),JS_ValueToObject() v.isString(); JSString *tmp =JS::ToString(cx, v); JSStringWrapper str(tmp); *ret = str.get(); jsonタイプ値を読み込みます.
bool jsval_to_vector2(JSContext *cx, JS::HandleValue vp/* js , js js */, cocos2d::Vec2* ret/* */)
{
// js
JS::RootedObject tmp(cx);
// js
JS::RootedValue jsx(cx);
JS::RootedValue jsy(cx);
double x, y;
bool ok = vp.isObject() &&//vp
JS_ValueToObject(cx, vp, &tmp) &&//vp
JS_GetProperty(cx, tmp, "x", &jsx) &&// json js
JS_GetProperty(cx, tmp, "y", &jsy) &&
JS::ToNumber(cx, jsx, &x) &&//js C++
JS::ToNumber(cx, jsy, &y);
JSB_PRECONDITION3(ok, cx, false, "Error processing arguments");
ret->x = (float)x;//
ret->y = (float)y;
return true;
}
js配列を読み込みます.bool jsval_to_std_vector_int( JSContext *cx, JS::HandleValue vp, std::vector<int>* ret)
{
// js
JS::RootedObject jsobj(cx);
// RootedValue, RootedObject, JSString, Number RootedValue
bool ok = vp.isObject() && JS_ValueToObject( cx, vp, &jsobj );
JSB_PRECONDITION3( ok, cx, false, "Error converting value to object");
JSB_PRECONDITION3( jsobj && JS_IsArrayObject( cx, jsobj), cx, false, "Object must be an array");
uint32_t len = 0;
//
JS_GetArrayLength(cx, jsobj, &len);
for (uint32_t i=0; i < len; i++)
{
// js
JS::RootedValue value(cx);
if (JS_GetElement(cx, jsobj, i, &value))
{
if (value.isNumber())
{
double number = 0.0;
//
ok = JS::ToNumber(cx, value, &number);
if (ok)
{
ret->push_back(static_cast<int>(number));
}
}
else
{
JS_ReportError(cx, "not supported type in array");
return false;
}
}
}
return true;
}
c++to js obj JS_NewObject JS_DefineProperty OBJECT_TO_JSVAL Array JS_NewArrayObject JS_SetElement OBJECT_TO_JSVAL int32_to_jsval std_string_to_jsvalはjsonタイプ値を作成します.
jsval vector2_to_jsval(JSContext *cx, const cocos2d::Vec2& v)
{
// js
JS::RootedObject proto(cx);
JS::RootedObject parent(cx);
JS::RootedObject tmp(cx, JS_NewObject(cx, NULL, proto, parent));
if (!tmp) return JSVAL_NULL;
// x y
bool ok = JS_DefineProperty(cx, tmp, "x", v.x, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "y", v.y, JSPROP_ENUMERATE | JSPROP_PERMANENT);
if (ok) {
// jsval
return OBJECT_TO_JSVAL(tmp);
}
return JSVAL_NULL;
}
js配列を作成する
jsval std_vector_int_to_jsval( JSContext *cx, const std::vector<int>& v)
{
JS::RootedObject jsretArr(cx, JS_NewArrayObject(cx, 0));
int i = 0;
for (const int obj : v)
{
JS::RootedValue arrElement(cx);
arrElement = int32_to_jsval(cx, obj);
if (!JS_SetElement(cx, jsretArr, i, arrElement)) {
break;
}
++i;
}
return OBJECT_TO_JSVAL(jsretArr);
}
グローバル関数c++変調js js変調c++
//
// jsb_kenko_auto.h
// Fishing2d36JSB
//
// Created by TinyUlt on 11/16/15.
//
//
#ifndef jsb_jsb_kenko_auto_h
#define jsb_jsb_kenko_auto_h
#include "cocos2d.h"
#include "jsapi.h"
#include "jsfriendapi.h"
std::string os_info();
bool jsb_os_info(JSContext *cx, uint32_t argc, JS::Value *vp);
bool jsb_callback(JSContext *cx, uint32_t argc, JS::Value *vp);
void register_jsb_kenko_all(JSContext* cx, JS::HandleObject obj);
#endif
//
// jsb_kenko_auto.cpp
// Fishing2d36JSB
//
// Created by TinyUlt on 11/16/15.
//
//
#include "jsb_kenko_auto.h"
#include "cocos2d_specifics.hpp"
std::string os_info() {
CCLOG("it's c++ os_info here");
return "os_info";
}
bool jsb_os_info(JSContext *cx, uint32_t argc, JS::Value *vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (argc == 0) {
std::string ret = os_info();
jsval jsret = JSVAL_NULL;
jsret = std_string_to_jsval(cx, ret);
args.rval().set(jsret);
return true;
}
JS_ReportError(cx, "js_FishAlg_FishAlg_getOutRotation3D : wrong number of arguments: %d, was expecting %d", argc, 0);
return false;
}
bool jsb_callback(JSContext *cx, uint32_t argc, JS::Value *vp) {
CCLOG("it's c++ testCallback here");
JSContext* jc = ScriptingCore::getInstance()->getGlobalContext();
//
// :http://www.tairan.com/archives/4902
//jsval v[2];
//v[0] = int32_to_jsval(jc, 32);
//v[1] = int32_to_jsval(jc, 12);
// ScriptingCore ,
//js_proxy_t * p = jsb_get_native_proxy();
//return ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(p->obj), "cpp_callback", 2, v); //2 ,v
//
jsval ret;
return ScriptingCore::getInstance()->evalString("cpp_callback(2,3)", &ret);
}
void register_jsb_kenko_all(JSContext *cx, JS::HandleObject obj) {
JS_DefineFunction(cx, obj, "os_Info", jsb_os_info, 0, 0); // osInfo js
JS_DefineFunction(cx, obj, "test_cpp_callback", jsb_callback, 0, 0);
// JS_DefineFunction(cx, tmpObj, "getInstance", js_PlistParser_getInstance, 0, JSPROP_READONLY | JSPROP_PERMANENT);
}
function cpp_callback(a, b) {
cc.log("cpp return two integer: " + a + " " + b);
}
cc.log("js get from c++: " + os_Info());
test_cpp_callback();
c++クラスのコールバック関数
//
// Network.h
// cocos2d_libs
//
// Created by TinyUlt on 11/16/15.
//
//
#ifndef __cocos2d_libs__Network__
#define __cocos2d_libs__Network__
#include <stdio.h>
class Network{
public:
Network();
~Network();
bool OnMessage();
};
#endif /* defined(__cocos2d_libs__Network__) */
//
// Network.cpp
// cocos2d_libs
//
// Created by TinyUlt on 11/16/15.
//
//
#include "Network.h"
#include "cocos2d.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "cocos2d_specifics.hpp"
Network::Network(){
}
Network::~Network(){
}
bool Network::OnMessage(){
js_proxy_t * p = jsb_get_native_proxy(this);
jsval retval;
JSContext* jc = ScriptingCore::getInstance()->getGlobalContext();
// ,
jsval v[] = {
v[0] = int32_to_jsval(jc, 32),
v[1] =UINT_TO_JSVAL(88)
};
// ScriptingCore ,
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(p->obj), "callback", 2, v);
return true;
}
network.callback = function (i, j) {
log("network.callback " + i + j);
}
network.OnMessage();
js関数はc++に渡され、関数コールバックに使用されます.
//
// jsb_JS_APP_CB.hpp
// cocos2d_js_bindings
//
// Created by TinyUlt on 1/9/16.
//
//
#ifndef jsb_JS_APP_CB_hpp
#define jsb_JS_APP_CB_hpp
#include "jsapi.h"
#include "jsfriendapi.h"
void register_all_js_cpp_cb(JSContext* cx, JS::HandleObject global);
#endif /* jsb_JS_APP_CB_hpp */
//
// jsb_JS_APP_CB.cpp
// cocos2d_js_bindings
//
// Created by TinyUlt on 1/9/16.
//
//
#include "jsb_JS_APP_CB.hpp"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "ScriptingCore.h"
#include "cocos2d_specifics.hpp"
#include "jsb_TinyJSWork.hpp"
#include "TinyJSWork.h"
using namespace cocos2d;
static bool jsb_applyStorePay(JSContext *cx, uint32_t argc, jsval *vp)
{
JSObject *obj = JS_THIS_OBJECT(cx, vp);
js_proxy_t *proxy = jsb_get_js_proxy(obj);
TinyJSWork* cobj = (TinyJSWork *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "Invalid Native Object");
if(true){
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
int _type;
jsval_to_int32(cx, args.get(0), &_type);
int _proID;
jsval_to_int32(cx, args.get(1), &_proID);
int _gameID;
jsval_to_int32(cx, args.get(2), &_gameID);
std::shared_ptr<JSFunctionWrapper> func(new JSFunctionWrapper(cx, obj, args.get(3)));
cobj->applyStorePay((PurchasePlatform)_type, (ProductID)_proID, _gameID,[=](int purType, int proID, int gameID,bool paySuc)->bool{
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
jsval arg[4];
arg[0] = int32_to_jsval(cx, purType);
arg[1] = int32_to_jsval(cx, proID);
arg[2] = int32_to_jsval(cx, gameID);
arg[3] = bool_to_jsval(cx, paySuc);
JS::RootedValue rval(cx);
CCLOG(" js applyStorePay ");
bool ok = func->invoke(4, arg, &rval);
if (!ok && JS_IsExceptionPending(cx)) {
JS_ReportPendingException(cx);
}
});
return true;
});
return true;
}
}
extern JSObject* jsb_TinyJSWork_prototype;
void register_all_js_cpp_cb(JSContext* cx, JS::HandleObject global)
{
JS_DefineFunction(cx, JS::RootedObject(cx, jsb_TinyJSWork_prototype), "applyStorePay", jsb_applyStorePay, 4, JSPROP_ENUMERATE | JSPROP_PERMANENT);
}
#endif
typedef void TinyJSStoreCallback(int purType, int proID, int gameID,bool paySuc);
//
void applyStorePay(PurchasePlatform type, ProductID proID,int gameID, std::function<TinyJSStoreCallback> jsCallback);
テスト1
void SwimAlg::test1(){
}
bool js_SwimAlg_SwimAlg_test1(JSContext *cx, uint32_t argc/* */, jsval *vp)
{
//
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
//js c++
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
SwimAlg* cobj = (SwimAlg *)(proxy ? proxy->ptr : NULL);
// ,
JSB_PRECONDITION2( cobj, cx, false, "js_SwimAlg_SwimAlg_test1 : Invalid Native Object");
///
// 0
if (argc == 0) {
// c++
cobj->test1();
//
args.rval().setUndefined();
return true;
}
// 0
JS_ReportError(cx, "js_SwimAlg_SwimAlg_test1 : wrong number of arguments: %d, was expecting %d", argc, 0);
return false;
}
テスト2
void SwimAlg::test2(int i){
}
bool js_SwimAlg_SwimAlg_test2(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
bool ok = true;
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
SwimAlg* cobj = (SwimAlg *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "js_SwimAlg_SwimAlg_test2 : Invalid Native Object");
// 1
if (argc == 1) {
int arg0;
//js c++
ok &= jsval_to_int32(cx, args.get(0), (int32_t *)&arg0);
JSB_PRECONDITION2(ok, cx, false, "js_SwimAlg_SwimAlg_test2 : Error processing arguments");
//
cobj->test2(arg0);
args.rval().setUndefined();
return true;
}
JS_ReportError(cx, "js_SwimAlg_SwimAlg_test2 : wrong number of arguments: %d, was expecting %d", argc, 1);
return false;
}
テスト3
void SwimAlg::test3(int i, float f){
}
bool js_SwimAlg_SwimAlg_test3(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
bool ok = true;
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
SwimAlg* cobj = (SwimAlg *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "js_SwimAlg_SwimAlg_test3 : Invalid Native Object");
// 2
if (argc == 2) {
int arg0;
double arg1;
ok &= jsval_to_int32(cx, args.get(0), (int32_t *)&arg0);
//js c++
ok &= JS::ToNumber( cx, args.get(1), &arg1) && !isnan(arg1);
JSB_PRECONDITION2(ok, cx, false, "js_SwimAlg_SwimAlg_test3 : Error processing arguments");
cobj->test3(arg0, arg1);
args.rval().setUndefined();
return true;
}
JS_ReportError(cx, "js_SwimAlg_SwimAlg_test3 : wrong number of arguments: %d, was expecting %d", argc, 2);
return false;
}
テスト4
void SwimAlg::test4(double d, Vec2 v){
}
bool js_SwimAlg_SwimAlg_test4(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
bool ok = true;
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
SwimAlg* cobj = (SwimAlg *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "js_SwimAlg_SwimAlg_test4 : Invalid Native Object");
if (argc == 2) {
double arg0;
cocos2d::Vec2 arg1;
ok &= JS::ToNumber( cx, args.get(0), &arg0) && !isnan(arg0);
//js cc.p() c++ Vec2()
ok &= jsval_to_vector2(cx, args.get(1), &arg1);
JSB_PRECONDITION2(ok, cx, false, "js_SwimAlg_SwimAlg_test4 : Error processing arguments");
cobj->test4(arg0, arg1);
args.rval().setUndefined();
return true;
}
JS_ReportError(cx, "js_SwimAlg_SwimAlg_test4 : wrong number of arguments: %d, was expecting %d", argc, 2);
return false;
}
bool jsval_to_vector2(JSContext *cx, JS::HandleValue vp/* js , js js */, cocos2d::Vec2* ret/* */)
{
// js
JS::RootedObject tmp(cx);
// js
JS::RootedValue jsx(cx);
JS::RootedValue jsy(cx);
double x, y;
bool ok = vp.isObject() &&//vp
JS_ValueToObject(cx, vp, &tmp) &&//vp
JS_GetProperty(cx, tmp, "x", &jsx) &&// json js
JS_GetProperty(cx, tmp, "y", &jsy) &&
JS::ToNumber(cx, jsx, &x) &&//js C++
JS::ToNumber(cx, jsy, &y);
JSB_PRECONDITION3(ok, cx, false, "Error processing arguments");
ret->x = (float)x;//
ret->y = (float)y;
return true;
}
テスト5
int SwimAlg::test5(){
return 0;
}
bool js_SwimAlg_SwimAlg_test5(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
SwimAlg* cobj = (SwimAlg *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "js_SwimAlg_SwimAlg_test5 : Invalid Native Object");
if (argc == 0) {
//
int ret = cobj->test5();
//c++ js
jsval jsret = JSVAL_NULL;
jsret = int32_to_jsval(cx, ret);
//
args.rval().set(jsret);
return true;
}
JS_ReportError(cx, "js_SwimAlg_SwimAlg_test5 : wrong number of arguments: %d, was expecting %d", argc, 0);
return false;
}
テスト6
Vec2 SwimAlg::test6(){
return Vec2::ZERO;
}
bool js_SwimAlg_SwimAlg_test6(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
SwimAlg* cobj = (SwimAlg *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "js_SwimAlg_SwimAlg_test6 : Invalid Native Object");
if (argc == 0) {
cocos2d::Vec2 ret = cobj->test6();
jsval jsret = JSVAL_NULL;
//Vec2 cc.p();
jsret = vector2_to_jsval(cx, ret);
//
args.rval().set(jsret);
return true;
}
JS_ReportError(cx, "js_SwimAlg_SwimAlg_test6 : wrong number of arguments: %d, was expecting %d", argc, 0);
return false;
}
jsval vector2_to_jsval(JSContext *cx, const cocos2d::Vec2& v)
{
// js
JS::RootedObject proto(cx);
JS::RootedObject parent(cx);
JS::RootedObject tmp(cx, JS_NewObject(cx, NULL, proto, parent));
if (!tmp) return JSVAL_NULL;
// x y
bool ok = JS_DefineProperty(cx, tmp, "x", v.x, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "y", v.y, JSPROP_ENUMERATE | JSPROP_PERMANENT);
if (ok) {
// jsval
return OBJECT_TO_JSVAL(tmp);
}
return JSVAL_NULL;
}
テスト7
void SwimAlg::test7(std::vector<int> v){
}
bool jsval_to_std_vector_int( JSContext *cx, JS::HandleValue vp, std::vector<int>* ret)
{
// js
JS::RootedObject jsobj(cx);
// RootedValue, RootedObject, JSString, Number RootedValue
bool ok = vp.isObject() && JS_ValueToObject( cx, vp, &jsobj );
JSB_PRECONDITION3( ok, cx, false, "Error converting value to object");
JSB_PRECONDITION3( jsobj && JS_IsArrayObject( cx, jsobj), cx, false, "Object must be an array");
uint32_t len = 0;
//
JS_GetArrayLength(cx, jsobj, &len);
for (uint32_t i=0; i < len; i++)
{
// js
JS::RootedValue value(cx);
if (JS_GetElement(cx, jsobj, i, &value))
{
if (value.isNumber())
{
double number = 0.0;
//
ok = JS::ToNumber(cx, value, &number);
if (ok)
{
ret->push_back(static_cast<int>(number));
}
}
else
{
JS_ReportError(cx, "not supported type in array");
return false;
}
}
}
return true;
}
テスト8
void SwimAlg::test8(std::vector<Vec2> v){
}
bool js_SwimAlg_SwimAlg_test8(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
bool ok = true;
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
SwimAlg* cobj = (SwimAlg *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "js_SwimAlg_SwimAlg_test8 : Invalid Native Object");
if (argc == 1) {
std::vector<cocos2d::Vec2> arg0;
ok &= jsval_to_std_vector_ccvec2(cx, args.get(0), &arg0);
JSB_PRECONDITION2(ok, cx, false, "js_SwimAlg_SwimAlg_test8 : Error processing arguments");
cobj->test8(arg0);
args.rval().setUndefined();
return true;
}
JS_ReportError(cx, "js_SwimAlg_SwimAlg_test8 : wrong number of arguments: %d, was expecting %d", argc, 1);
return false;
}