Moved some Js objects implementation in another file.

Renamed Engine.Debug and Engine.Output to lower case to avoid confusion with constants.


git-svn-id: http://yate.null.ro/svn/yate/trunk@5035 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2012-05-02 15:11:48 +00:00
parent 3823269bad
commit 1eec7eb43b
4 changed files with 138 additions and 30 deletions

View File

@ -83,6 +83,7 @@ public:
OpcTrue,
OpcFalse,
OpcInclude,
OpcRequire,
};
inline JsCode()
: ExpEvaluator(C), m_label(0), m_depth(0)
@ -99,6 +100,8 @@ public:
virtual bool initialize(ScriptContext* context) const;
virtual bool evaluate(ScriptRun& runner, ObjList& results) const;
bool link();
JsObject* parseArray(const char*& expr, bool constOnly);
JsObject* parseObject(const char*& expr, bool constOnly);
protected:
virtual bool keywordChar(char c) const;
virtual int getKeyword(const char* str) const;
@ -118,7 +121,8 @@ protected:
virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context) const;
private:
ObjVector m_linked;
bool preProcessInclude(const char*& expr, GenObject* context);
ObjList m_included;
bool preProcessInclude(const char*& expr, bool once, GenObject* context);
bool evalList(ObjList& stack, GenObject* context) const;
bool evalVector(ObjList& stack, GenObject* context) const;
bool jumpToLabel(long int label, GenObject* context) const;
@ -196,6 +200,7 @@ static const TokenDict s_bools[] =
static const TokenDict s_preProc[] =
{
MAKEOP("#include", Include),
MAKEOP("#require", Require),
{ 0, 0 }
};
#undef MAKEOP
@ -427,7 +432,7 @@ char JsCode::skipComments(const char*& expr, GenObject* context) const
return c;
}
bool JsCode::preProcessInclude(const char*& expr, GenObject* context)
bool JsCode::preProcessInclude(const char*& expr, bool once, GenObject* context)
{
if (m_depth > 5)
return gotError("Possible recursive include");
@ -444,9 +449,18 @@ bool JsCode::preProcessInclude(const char*& expr, GenObject* context)
String str(start,expr-start-1);
DDebug(this,DebugAll,"Found include '%s'",str.safe());
parser->adjustPath(str);
m_depth++;
bool ok = parser->parseFile(str,true);
m_depth--;
str.trimSpaces();
bool ok = !str.null();
if (ok) {
bool already = m_included.find(str);
if (!(once && already)) {
m_depth++;
ok = parser->parseFile(str,true);
m_depth--;
if (ok && !already)
m_included.append(new String(str));
}
}
return ok || gotError("Failed to include " + str);
}
expr--;
@ -459,9 +473,11 @@ int JsCode::preProcess(const char*& expr, GenObject* context)
{
int rval = -1;
for (;;) {
switch ((JsOpcode)ExpEvaluator::getOperator(expr,s_preProc)) {
JsOpcode opc = (JsOpcode)ExpEvaluator::getOperator(expr,s_preProc);
switch (opc) {
case OpcInclude:
if (preProcessInclude(expr,context)) {
case OpcRequire:
if (preProcessInclude(expr,(OpcRequire == opc),context)) {
if (rval < 0)
rval = 1;
else
@ -731,6 +747,31 @@ bool JsCode::getSeparator(const char*& expr, bool remove)
return ExpEvaluator::getSeparator(expr,remove);
}
// Parse an inline Javascript [ array ]
JsObject* JsCode::parseArray(const char*& expr, bool constOnly)
{
if (skipComments(expr) != '[')
return 0;
expr++;
JsObject* jso = new JsObject;
if (skipComments(expr) != ']')
TelEngine::destruct(jso);
return jso;
}
// Parse an inline Javascript { object }
JsObject* JsCode::parseObject(const char*& expr, bool constOnly)
{
if (skipComments(expr) != '{')
return 0;
expr++;
JsObject* jso = new JsObject;
if (skipComments(expr) != '}')
TelEngine::destruct(jso);
return jso;
}
bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, GenObject* context) const
{
switch ((JsOpcode)oper.opcode()) {
@ -1098,4 +1139,13 @@ ScriptRun::Status JsParser::eval(const String& text, ExpOperation** result, Scri
return rval;
}
// Parse JSON using native methods
JsObject* JsParser::parseJSON(const char* text)
{
JsCode* code = new JsCode;
JsObject* jso = code->parseObject(text,true);
TelEngine::destruct(code);
return jso;
}
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -50,17 +50,11 @@ class JsArray : public JsObject
public:
inline JsArray(Mutex* mtx)
: JsObject("Array",mtx)
{ }
};
// Object constructor
class JsConstructor : public JsFunction
{
YCLASS(JsConstructor,JsFunction)
public:
inline JsConstructor(Mutex* mtx)
: JsFunction(mtx)
{ }
{
params().addParam(new ExpFunction("push"));
}
protected:
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
};
// Object object
@ -134,6 +128,7 @@ JsObject::JsObject(const char* name, Mutex* mtx, bool frozen)
params().addParam(new ExpFunction("freeze"));
params().addParam(new ExpFunction("isFrozen"));
params().addParam(new ExpFunction("toString"));
params().addParam(new ExpFunction("hasOwnProperty"));
}
JsObject::~JsObject()
@ -230,6 +225,17 @@ bool JsObject::runNative(ObjList& stack, const ExpOperation& oper, GenObject* co
ExpEvaluator::pushOne(stack,new ExpOperation(frozen()));
else if (oper.name() == YSTRING("toString"))
ExpEvaluator::pushOne(stack,new ExpOperation(params()));
else if (oper.name() == YSTRING("hasOwnProperty")) {
bool ok = true;
for (long int i = oper.number(); i; i--) {
ExpOperation* op = popValue(stack,context);
if (!op)
continue;
ok = ok && params().getParam(*op);
TelEngine::destruct(op);
}
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
}
else
return false;
return true;
@ -276,6 +282,13 @@ bool JsObjectObj::runNative(ObjList& stack, const ExpOperation& oper, GenObject*
return true;
}
bool JsArray::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
{
return JsObject::runNative(stack,oper,context);
}
bool JsMath::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
{
if (oper.name() == YSTRING("abs")) {
@ -328,6 +341,30 @@ bool JsDate::runNative(ObjList& stack, const ExpOperation& oper, GenObject* cont
}
JsFunction::JsFunction(Mutex* mtx)
: JsObject("Function",mtx,true)
{
params().addParam(new ExpFunction("apply"));
params().addParam(new ExpFunction("call"));
}
bool JsFunction::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
{
if (oper.name() == YSTRING("apply")) {
// func.apply(new_this,["array","of","params",...])
if (oper.number() != 2)
return false;
}
else if (oper.name() == YSTRING("call")) {
// func.call(new_this,param1,param2,...)
if (!oper.number())
return false;
}
else
return JsObject::runNative(stack,oper,context);
return true;
}
bool JsFunction::runDefined(ObjList& stack, const ExpOperation& oper, GenObject* context)
{
return false;

View File

@ -307,14 +307,14 @@ public:
/**
* Dump a list of operations according to current operators dictionary
* @param codes List of operation codes
* @result String representation of operations
* @return String representation of operations
*/
inline String dump(const ObjList& codes) const
{ String s; dump(codes,s); return s; }
/**
* Dump the postfix expression according to current operators dictionary
* @result String representation of operations
* @return String representation of operations
*/
inline String dump() const
{ String s; dump(s); return s; }
@ -1475,9 +1475,7 @@ public:
* Constructor
* @param mtx Pointer to the mutex that serializes this object
*/
inline JsFunction(Mutex* mtx = 0)
: JsObject("Function",mtx,true)
{ }
JsFunction(Mutex* mtx = 0);
/**
* Try to evaluate a single user defined method
@ -1489,6 +1487,17 @@ public:
*/
virtual bool runDefined(ObjList& stack, const ExpOperation& oper, GenObject* context);
protected:
/**
* Try to evaluate a single native method
* @param stack Evaluation stack in use, parameters are popped off this stack
* and results are pushed back on stack
* @param oper Function to evaluate
* @param context Pointer to arbitrary object passed from evaluation methods
* @return True if evaluation succeeded
*/
virtual bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
};
/**
@ -1558,6 +1567,13 @@ public:
*/
static ScriptRun::Status eval(const String& text, ExpOperation** result = 0, ScriptContext* context = 0);
/**
* Parse a complete block of JSON text
* @param text JSON text to parse
* @return JsObject holding the content of JSON, must be dereferenced after use, NULL if parse error
*/
static JsObject* parseJSON(const char* text);
private:
String m_basePath;
};

View File

@ -54,8 +54,13 @@ private:
class JsAssist : public ChanAssist
{
public:
enum State {
NotRouted,
Routing,
ReRoute,
};
inline JsAssist(ChanAssistList* list, const String& id, ScriptRun* runner)
: ChanAssist(list, id), m_runner(runner)
: ChanAssist(list, id), m_runner(runner), m_state(NotRouted)
{ }
virtual ~JsAssist();
virtual void msgStartup(Message& msg);
@ -70,6 +75,7 @@ public:
private:
bool runFunction(const char* name, Message& msg);
ScriptRun* m_runner;
State m_state;
};
#define MKDEBUG(lvl) params().addParam(new ExpOperation((long int)Debug ## lvl,"Debug" # lvl))
@ -91,8 +97,8 @@ public:
MKDEBUG(Note);
MKDEBUG(Info);
MKDEBUG(All);
params().addParam(new ExpFunction("Output"));
params().addParam(new ExpFunction("Debug"));
params().addParam(new ExpFunction("output"));
params().addParam(new ExpFunction("debug"));
}
static void initialize(ScriptContext* context);
protected:
@ -196,7 +202,7 @@ static inline void addObject(NamedList& params, const char* name, JsObject* obj)
bool JsEngine::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
{
if (oper.name() == YSTRING("Output")) {
if (oper.name() == YSTRING("output")) {
String str;
for (long int i = oper.number(); i; i--) {
ExpOperation* op = popValue(stack,context);
@ -208,18 +214,16 @@ bool JsEngine::runNative(ObjList& stack, const ExpOperation& oper, GenObject* co
if (str)
Output("%s",str.c_str());
}
else if (oper.name() == YSTRING("Debug")) {
else if (oper.name() == YSTRING("debug")) {
int level = DebugNote;
String str;
for (long int i = oper.number(); i; i--) {
ExpOperation* op = popValue(stack,context);
if (!op)
continue;
Debug(DebugTest,"Popped [%ld] '%s' %ld",i,op->c_str(),op->number());
if ((i == 1) && oper.number() > 1 && op->isInteger())
level = op->number();
else if (*op) {
Debug(DebugTest,"Prepend '%s'",op->c_str());
if (str)
str = *op + " " + str;
else
@ -535,6 +539,7 @@ bool JsAssist::msgPreroute(Message& msg)
bool JsAssist::msgRoute(Message& msg)
{
m_state = Routing;
return false;
}