2012-08-28 10:22:36 +08:00
|
|
|
//
|
|
|
|
// ScriptingCore.h
|
|
|
|
// testmonkey
|
|
|
|
//
|
|
|
|
// Created by Rolando Abarca on 3/14/12.
|
|
|
|
// Copyright (c) 2012 Zynga Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef __SCRIPTING_CORE_H__
|
|
|
|
#define __SCRIPTING_CORE_H__
|
|
|
|
|
|
|
|
#include <assert.h>
|
2013-07-21 19:10:22 +08:00
|
|
|
#include <memory>
|
2012-08-28 10:22:36 +08:00
|
|
|
#include "cocos2d.h"
|
2013-01-12 06:01:36 +08:00
|
|
|
#include "js_bindings_config.h"
|
2013-01-12 06:29:40 +08:00
|
|
|
#include "js_bindings_core.h"
|
2012-08-28 10:22:36 +08:00
|
|
|
#include "jsapi.h"
|
|
|
|
#include "jsfriendapi.h"
|
|
|
|
#include "spidermonkey_specifics.h"
|
|
|
|
|
|
|
|
void js_log(const char *format, ...);
|
|
|
|
|
|
|
|
using namespace cocos2d;
|
2013-01-12 06:01:36 +08:00
|
|
|
using namespace std;
|
2012-08-28 10:22:36 +08:00
|
|
|
|
|
|
|
typedef void (*sc_register_sth)(JSContext* cx, JSObject* global);
|
|
|
|
|
|
|
|
void registerDefaultClasses(JSContext* cx, JSObject* global);
|
|
|
|
|
2013-01-17 06:02:05 +08:00
|
|
|
|
2013-06-20 14:33:59 +08:00
|
|
|
class SimpleRunLoop : public Object
|
2013-01-17 06:02:05 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
void update(float d);
|
|
|
|
};
|
|
|
|
|
2013-06-20 14:33:59 +08:00
|
|
|
class ScriptingCore : public ScriptEngineProtocol
|
2012-08-28 10:22:36 +08:00
|
|
|
{
|
2012-10-19 08:44:41 +08:00
|
|
|
JSRuntime *rt_;
|
|
|
|
JSContext *cx_;
|
|
|
|
JSObject *global_;
|
2012-11-16 03:14:57 +08:00
|
|
|
JSObject *debugGlobal_;
|
2013-01-17 06:02:05 +08:00
|
|
|
SimpleRunLoop* runLoop;
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
ScriptingCore();
|
|
|
|
public:
|
|
|
|
~ScriptingCore();
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
static ScriptingCore *getInstance() {
|
2012-08-29 14:55:03 +08:00
|
|
|
static ScriptingCore* pInstance = NULL;
|
|
|
|
if (pInstance == NULL) {
|
|
|
|
pInstance = new ScriptingCore();
|
|
|
|
}
|
|
|
|
return pInstance;
|
2012-08-28 10:22:36 +08:00
|
|
|
};
|
|
|
|
|
2012-08-31 21:23:23 +08:00
|
|
|
virtual ccScriptType getScriptType() { return kScriptTypeJavascript; };
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
2013-06-20 14:33:59 +08:00
|
|
|
@brief Remove Object from lua state
|
2012-08-28 10:22:36 +08:00
|
|
|
@param object to remove
|
|
|
|
*/
|
2013-06-20 14:33:59 +08:00
|
|
|
virtual void removeScriptObjectByObject(Object* pObj);
|
2012-08-28 12:04:51 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
@brief Execute script code contained in the given string.
|
|
|
|
@param codes holding the valid script code that should be executed.
|
|
|
|
@return 0 if the string is excuted correctly.
|
|
|
|
@return other if the string is excuted wrongly.
|
|
|
|
*/
|
2012-08-29 14:55:03 +08:00
|
|
|
virtual int executeString(const char* codes) { return 0; }
|
2013-03-16 21:14:39 +08:00
|
|
|
void pauseSchedulesAndActions(js_proxy_t* p);
|
|
|
|
void resumeSchedulesAndActions(js_proxy_t* p);
|
|
|
|
void cleanupSchedulesAndActions(js_proxy_t* p);
|
2012-10-23 05:51:35 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
@brief Execute a script file.
|
|
|
|
@param filename String object holding the filename of the script file that is to be executed
|
|
|
|
*/
|
2012-08-29 14:55:03 +08:00
|
|
|
virtual int executeScriptFile(const char* filename) { return 0; }
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
@brief Execute a scripted global function.
|
|
|
|
@brief The function should not take any parameters and should return an integer.
|
|
|
|
@param functionName String object holding the name of the function, in the global script environment, that is to be executed.
|
|
|
|
@return The integer value returned from the script function.
|
|
|
|
*/
|
2012-08-29 14:55:03 +08:00
|
|
|
virtual int executeGlobalFunction(const char* functionName) { return 0; }
|
2012-09-11 14:02:33 +08:00
|
|
|
|
2013-07-22 17:12:53 +08:00
|
|
|
virtual int sendEvent(ScriptEvent* message) override;
|
2013-04-15 22:50:07 +08:00
|
|
|
|
|
|
|
virtual bool handleAssert(const char *msg) { return false; }
|
2012-09-11 14:02:33 +08:00
|
|
|
|
2013-06-20 14:33:59 +08:00
|
|
|
bool executeFunctionWithObjectData(Node *self, const char *name, JSObject *obj);
|
2013-03-14 18:14:16 +08:00
|
|
|
JSBool executeFunctionWithOwner(jsval owner, const char *name, uint32_t argc = 0, jsval* vp = NULL, jsval* retVal = NULL);
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2013-07-25 20:52:16 +08:00
|
|
|
void executeJSFunctionWithThisObj(jsval thisObj, jsval callback, uint32_t argc = 0, jsval* vp = NULL, jsval* retVal = NULL);
|
2012-08-28 10:22:36 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* will eval the specified string
|
|
|
|
* @param string The string with the javascript code to be evaluated
|
|
|
|
* @param outVal The jsval that will hold the return value of the evaluation.
|
|
|
|
* Can be NULL.
|
|
|
|
*/
|
2012-10-19 08:44:41 +08:00
|
|
|
JSBool evalString(const char *string, jsval *outVal, const char *filename = NULL, JSContext* cx = NULL, JSObject* global = NULL);
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
* will run the specified string
|
|
|
|
* @param string The path of the script to be run
|
|
|
|
*/
|
2012-10-19 08:44:41 +08:00
|
|
|
JSBool runScript(const char *path, JSObject* global = NULL, JSContext* cx = NULL);
|
2012-08-28 10:22:36 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* initialize everything
|
|
|
|
*/
|
|
|
|
void start();
|
|
|
|
|
2013-02-22 00:33:37 +08:00
|
|
|
/**
|
|
|
|
* cleanup everything
|
|
|
|
*/
|
|
|
|
void cleanup();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* cleanup everything then initialize everything
|
|
|
|
*/
|
|
|
|
void reset();
|
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
* will add the register_sth callback to the list of functions that need to be called
|
|
|
|
* after the creation of the context
|
|
|
|
*/
|
|
|
|
void addRegisterCallback(sc_register_sth callback);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Will create a new context. If one is already there, it will destroy the old context
|
|
|
|
* and create a new one.
|
|
|
|
*/
|
|
|
|
void createGlobalContext();
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-09-19 09:44:21 +08:00
|
|
|
static void removeAllRoots(JSContext *cx);
|
2013-02-22 00:33:37 +08:00
|
|
|
|
|
|
|
|
2013-09-12 16:02:16 +08:00
|
|
|
int executeCustomTouchEvent(TouchEvent::EventCode eventType,
|
2013-06-20 14:33:59 +08:00
|
|
|
Touch *pTouch, JSObject *obj, jsval &retval);
|
2013-09-12 16:02:16 +08:00
|
|
|
int executeCustomTouchEvent(TouchEvent::EventCode eventType,
|
2013-06-20 14:33:59 +08:00
|
|
|
Touch *pTouch, JSObject *obj);
|
2013-09-12 16:02:16 +08:00
|
|
|
int executeCustomTouchesEvent(TouchEvent::EventCode eventType,
|
|
|
|
const std::vector<Touch*>& touches, JSObject *obj);
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
* @return the global context
|
|
|
|
*/
|
|
|
|
JSContext* getGlobalContext() {
|
2012-10-19 08:44:41 +08:00
|
|
|
return cx_;
|
2012-08-28 10:22:36 +08:00
|
|
|
};
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
* @param cx
|
|
|
|
* @param message
|
|
|
|
* @param report
|
|
|
|
*/
|
|
|
|
static void reportError(JSContext *cx, const char *message, JSErrorReport *report);
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
* Log something using CCLog
|
|
|
|
* @param cx
|
|
|
|
* @param argc
|
|
|
|
* @param vp
|
|
|
|
*/
|
|
|
|
static JSBool log(JSContext *cx, uint32_t argc, jsval *vp);
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
JSBool setReservedSpot(uint32_t i, JSObject *obj, jsval value);
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
* run a script from script :)
|
|
|
|
*/
|
|
|
|
static JSBool executeScript(JSContext *cx, uint32_t argc, jsval *vp);
|
2013-02-22 00:33:37 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
/**
|
|
|
|
* Force a cycle of GC
|
|
|
|
* @param cx
|
|
|
|
* @param argc
|
|
|
|
* @param vp
|
|
|
|
*/
|
|
|
|
static JSBool forceGC(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
static JSBool dumpRoot(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
static JSBool addRootJS(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
static JSBool removeRootJS(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
|
2012-11-16 03:14:57 +08:00
|
|
|
/**
|
|
|
|
* enable the debug environment
|
|
|
|
*/
|
2013-01-12 06:01:36 +08:00
|
|
|
void debugProcessInput(string str);
|
2012-11-16 03:14:57 +08:00
|
|
|
void enableDebugger();
|
|
|
|
JSObject* getDebugGlobal() { return debugGlobal_; }
|
2013-03-12 22:03:37 +08:00
|
|
|
JSObject* getGlobalObject() { return global_; }
|
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
private:
|
|
|
|
void string_report(jsval val);
|
2013-07-22 17:12:53 +08:00
|
|
|
|
|
|
|
int handleTouchesEvent(void* data);
|
|
|
|
int handleTouchEvent(void* data);
|
|
|
|
int handleNodeEvent(void* data);
|
|
|
|
int handleMenuClickedEvent(void* data);
|
|
|
|
int handleAccelerometerEvent(void* data);
|
|
|
|
int handleKeypadEvent(void* data);
|
2012-08-28 10:22:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// some utility functions
|
|
|
|
// to native
|
2013-01-11 13:54:57 +08:00
|
|
|
JSBool jsval_to_int32( JSContext *cx, jsval vp, int32_t *ret );
|
|
|
|
JSBool jsval_to_uint32( JSContext *cx, jsval vp, uint32_t *ret );
|
|
|
|
JSBool jsval_to_uint16( JSContext *cx, jsval vp, uint16_t *ret );
|
|
|
|
JSBool jsval_to_long_long(JSContext *cx, jsval v, long long* ret);
|
|
|
|
JSBool jsval_to_std_string(JSContext *cx, jsval v, std::string* ret);
|
2013-06-20 14:33:59 +08:00
|
|
|
JSBool jsval_to_ccpoint(JSContext *cx, jsval v, Point* ret);
|
|
|
|
JSBool jsval_to_ccrect(JSContext *cx, jsval v, Rect* ret);
|
|
|
|
JSBool jsval_to_ccsize(JSContext *cx, jsval v, Size* ret);
|
2013-07-08 15:18:57 +08:00
|
|
|
JSBool jsval_to_cccolor4b(JSContext *cx, jsval v, Color4B* ret);
|
|
|
|
JSBool jsval_to_cccolor4f(JSContext *cx, jsval v, Color4F* ret);
|
|
|
|
JSBool jsval_to_cccolor3b(JSContext *cx, jsval v, Color3B* ret);
|
2013-06-20 14:33:59 +08:00
|
|
|
JSBool jsval_to_ccarray_of_CCPoint(JSContext* cx, jsval v, Point **points, int *numPoints);
|
|
|
|
JSBool jsval_to_ccarray(JSContext* cx, jsval v, Array** ret);
|
|
|
|
JSBool jsval_to_ccdictionary(JSContext* cx, jsval v, Dictionary** ret);
|
|
|
|
JSBool jsval_to_ccacceleration(JSContext* cx,jsval v, Acceleration* ret);
|
|
|
|
JSBool jsvals_variadic_to_ccarray( JSContext *cx, jsval *vp, int argc, Array** ret);
|
|
|
|
JSBool jsval_to_ccaffinetransform(JSContext* cx, jsval v, AffineTransform* ret);
|
2013-07-08 15:18:57 +08:00
|
|
|
JSBool jsval_to_FontDefinition( JSContext *cx, jsval vp, FontDefinition* ret );
|
2012-11-07 03:03:07 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
// from native
|
2013-01-11 13:54:57 +08:00
|
|
|
jsval int32_to_jsval( JSContext *cx, int32_t l);
|
|
|
|
jsval uint32_to_jsval( JSContext *cx, uint32_t number );
|
2012-08-28 10:22:36 +08:00
|
|
|
jsval long_long_to_jsval(JSContext* cx, long long v);
|
2013-07-08 15:18:57 +08:00
|
|
|
jsval std_string_to_jsval(JSContext* cx, const string& v);
|
2013-04-17 16:08:48 +08:00
|
|
|
jsval c_string_to_jsval(JSContext* cx, const char* v, size_t length = -1);
|
2013-07-08 15:18:57 +08:00
|
|
|
jsval ccpoint_to_jsval(JSContext* cx, const Point& v);
|
|
|
|
jsval ccrect_to_jsval(JSContext* cx, const Rect& v);
|
|
|
|
jsval ccsize_to_jsval(JSContext* cx, const Size& v);
|
|
|
|
jsval cccolor4b_to_jsval(JSContext* cx, const Color4B& v);
|
|
|
|
jsval cccolor4f_to_jsval(JSContext* cx, const Color4F& v);
|
|
|
|
jsval cccolor3b_to_jsval(JSContext* cx, const Color3B& v);
|
2013-06-20 14:33:59 +08:00
|
|
|
jsval ccdictionary_to_jsval(JSContext* cx, Dictionary *dict);
|
|
|
|
jsval ccarray_to_jsval(JSContext* cx, Array *arr);
|
2013-07-08 15:18:57 +08:00
|
|
|
jsval ccacceleration_to_jsval(JSContext* cx, const Acceleration& v);
|
|
|
|
jsval ccaffinetransform_to_jsval(JSContext* cx, const AffineTransform& t);
|
|
|
|
jsval FontDefinition_to_jsval(JSContext* cx, const FontDefinition& t);
|
2012-10-19 08:44:41 +08:00
|
|
|
|
2012-11-16 03:14:57 +08:00
|
|
|
JSObject* NewGlobalObject(JSContext* cx, bool debug = false);
|
|
|
|
JSBool jsStartDebugger(JSContext* cx, unsigned argc, jsval* vp);
|
|
|
|
JSBool jsGetScript(JSContext* cx, unsigned argc, jsval* vp);
|
2012-10-29 15:10:13 +08:00
|
|
|
|
2013-01-12 06:01:36 +08:00
|
|
|
JSBool JSBDebug_StartDebugger(JSContext* cx, unsigned argc, jsval* vp);
|
|
|
|
JSBool JSBDebug_BufferRead(JSContext* cx, unsigned argc, jsval* vp);
|
|
|
|
JSBool JSBDebug_BufferWrite(JSContext* cx, unsigned argc, jsval* vp);
|
|
|
|
JSBool JSBDebug_LockExecution(JSContext* cx, unsigned argc, jsval* vp);
|
|
|
|
JSBool JSBDebug_UnlockExecution(JSContext* cx, unsigned argc, jsval* vp);
|
2012-10-19 08:44:41 +08:00
|
|
|
|
2012-11-16 03:14:37 +08:00
|
|
|
// just a simple utility to avoid mem leaking when using JSString
|
|
|
|
class JSStringWrapper
|
|
|
|
{
|
|
|
|
JSString* string;
|
|
|
|
const char* buffer;
|
|
|
|
public:
|
|
|
|
JSStringWrapper() {
|
|
|
|
buffer = NULL;
|
|
|
|
}
|
|
|
|
JSStringWrapper(JSString* str, JSContext* cx = NULL) {
|
|
|
|
set(str, cx);
|
|
|
|
}
|
|
|
|
JSStringWrapper(jsval val, JSContext* cx = NULL) {
|
|
|
|
set(val, cx);
|
|
|
|
}
|
|
|
|
~JSStringWrapper() {
|
|
|
|
if (buffer) {
|
2013-03-13 18:10:54 +08:00
|
|
|
//JS_free(ScriptingCore::getInstance()->getGlobalContext(), (void*)buffer);
|
|
|
|
delete[] buffer;
|
2012-11-16 03:14:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
void set(jsval val, JSContext* cx) {
|
|
|
|
if (val.isString()) {
|
2013-02-27 15:16:49 +08:00
|
|
|
this->set(val.toString(), cx);
|
2012-11-16 03:14:37 +08:00
|
|
|
} else {
|
|
|
|
buffer = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void set(JSString* str, JSContext* cx) {
|
|
|
|
string = str;
|
|
|
|
if (!cx) {
|
|
|
|
cx = ScriptingCore::getInstance()->getGlobalContext();
|
2013-03-13 18:10:54 +08:00
|
|
|
|
2012-11-16 03:14:37 +08:00
|
|
|
}
|
2013-03-13 18:10:54 +08:00
|
|
|
// JS_EncodeString isn't supported in SpiderMonkey ff19.0.
|
|
|
|
//buffer = JS_EncodeString(cx, string);
|
|
|
|
unsigned short* pStrUTF16 = (unsigned short*)JS_GetStringCharsZ(cx, str);
|
|
|
|
buffer = cc_utf16_to_utf8(pStrUTF16, -1, NULL, NULL);
|
2012-11-16 03:14:37 +08:00
|
|
|
}
|
2013-01-12 06:01:36 +08:00
|
|
|
std::string get() {
|
2012-12-29 13:54:46 +08:00
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2012-11-16 03:14:37 +08:00
|
|
|
operator std::string() {
|
|
|
|
return std::string(buffer);
|
|
|
|
}
|
|
|
|
operator char*() {
|
|
|
|
return (char*)buffer;
|
|
|
|
}
|
2013-03-08 15:15:08 +08:00
|
|
|
private:
|
|
|
|
/* Copy and assignment are not supported. */
|
|
|
|
JSStringWrapper(const JSStringWrapper &another);
|
|
|
|
JSStringWrapper &operator=(const JSStringWrapper &another);
|
2012-11-16 03:14:37 +08:00
|
|
|
};
|
|
|
|
|
2013-07-13 10:30:08 +08:00
|
|
|
// wraps a function and "this" object
|
|
|
|
class JSFunctionWrapper
|
|
|
|
{
|
|
|
|
JSContext *_cx;
|
|
|
|
JSObject *_jsthis;
|
|
|
|
jsval _fval;
|
|
|
|
public:
|
|
|
|
JSFunctionWrapper(JSContext* cx, JSObject *jsthis, jsval fval)
|
|
|
|
: _cx(cx)
|
|
|
|
, _jsthis(jsthis)
|
|
|
|
, _fval(fval)
|
|
|
|
{
|
|
|
|
JS_AddNamedValueRoot(cx, &this->_fval, "JSFunctionWrapper");
|
|
|
|
JS_AddNamedObjectRoot(cx, &this->_jsthis, "JSFunctionWrapper");
|
|
|
|
}
|
|
|
|
~JSFunctionWrapper() {
|
|
|
|
JS_RemoveValueRoot(this->_cx, &this->_fval);
|
|
|
|
JS_RemoveObjectRoot(this->_cx, &this->_jsthis);
|
|
|
|
}
|
|
|
|
JSBool invoke(unsigned int argc, jsval *argv, jsval &rval) {
|
|
|
|
return JS_CallFunctionValue(this->_cx, this->_jsthis, this->_fval, argc, argv, &rval);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
/* Copy and assignment are not supported. */
|
|
|
|
JSFunctionWrapper(const JSFunctionWrapper &another);
|
|
|
|
JSFunctionWrapper &operator=(const JSFunctionWrapper &another);
|
|
|
|
};
|
|
|
|
|
2012-11-30 22:00:30 +08:00
|
|
|
JSBool jsb_set_reserved_slot(JSObject *obj, uint32_t idx, jsval value);
|
|
|
|
JSBool jsb_get_reserved_slot(JSObject *obj, uint32_t idx, jsval& ret);
|
|
|
|
|
2013-06-03 22:31:24 +08:00
|
|
|
js_proxy_t* jsb_new_proxy(void* nativeObj, JSObject* jsObj);
|
|
|
|
js_proxy_t* jsb_get_native_proxy(void* nativeObj);
|
|
|
|
js_proxy_t* jsb_get_js_proxy(JSObject* jsObj);
|
|
|
|
void jsb_remove_proxy(js_proxy_t* nativeProxy, js_proxy_t* jsProxy);
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* __SCRIPTING_CORE_H__ */
|