Added string properties and methods that apply to all non-JS objects.
Fixed the name resolution to allow the pseudo properties. git-svn-id: http://yate.null.ro/svn/yate/trunk@5081 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
24670814da
commit
7b7b3abdf9
|
@ -886,6 +886,8 @@ ExpOperation* ExpEvaluator::popValue(ObjList& stack, GenObject* context) const
|
|||
ExpOperation* oper = popOne(stack);
|
||||
if (!oper || (oper->opcode() != OpcField))
|
||||
return oper;
|
||||
XDebug(DebugAll,"ExpEvaluator::popValue() field '%s' [%p]",
|
||||
oper->name().c_str(),this);
|
||||
bool ok = runField(stack,*oper,context);
|
||||
TelEngine::destruct(oper);
|
||||
return ok ? popOne(stack) : 0;
|
||||
|
|
|
@ -45,6 +45,8 @@ public:
|
|||
private:
|
||||
GenObject* resolveTop(ObjList& stack, const String& name, GenObject* context);
|
||||
GenObject* resolve(ObjList& stack, String& name, GenObject* context);
|
||||
bool runStringFunction(GenObject* obj, const String& name, ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
bool runStringField(GenObject* obj, const String& name, ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
};
|
||||
|
||||
class JsNull : public JsObject
|
||||
|
@ -301,6 +303,8 @@ bool JsContext::runFunction(ObjList& stack, const ExpOperation& oper, GenObject*
|
|||
ExpOperation op(oper,name);
|
||||
return ext->runFunction(stack,op,context);
|
||||
}
|
||||
if (runStringFunction(o,name,stack,oper,context))
|
||||
return true;
|
||||
}
|
||||
if (name == YSTRING("isNaN")) {
|
||||
bool nan = true;
|
||||
|
@ -343,10 +347,105 @@ bool JsContext::runField(ObjList& stack, const ExpOperation& oper, GenObject* co
|
|||
ExpOperation op(oper,name);
|
||||
return ext->runField(stack,op,context);
|
||||
}
|
||||
if (runStringField(o,name,stack,oper,context))
|
||||
return true;
|
||||
}
|
||||
return JsObject::runField(stack,oper,context);
|
||||
}
|
||||
|
||||
bool JsContext::runStringFunction(GenObject* obj, const String& name, ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
const String* str = YOBJECT(String,obj);
|
||||
if (!str)
|
||||
return false;
|
||||
if (name == YSTRING("charAt")) {
|
||||
int idx = 0;
|
||||
ObjList args;
|
||||
if (extractArgs(stack,oper,context,args)) {
|
||||
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
||||
if (op && op->isInteger())
|
||||
idx = op->number();
|
||||
}
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(String(str->at(idx))));
|
||||
return true;
|
||||
}
|
||||
if (name == YSTRING("indexOf")) {
|
||||
int idx = -1;
|
||||
ObjList args;
|
||||
if (extractArgs(stack,oper,context,args)) {
|
||||
const String* what = static_cast<String*>(args[0]);
|
||||
if (what) {
|
||||
ExpOperation* from = static_cast<ExpOperation*>(args[1]);
|
||||
int offs = (from && from->isInteger()) ? from->number() : 0;
|
||||
if (offs < 0)
|
||||
offs = 0;
|
||||
idx = str->find(*what,offs);
|
||||
}
|
||||
}
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation((long int)idx));
|
||||
return true;
|
||||
}
|
||||
if (name == YSTRING("substr")) {
|
||||
ObjList args;
|
||||
int offs = 0;
|
||||
int len = -1;
|
||||
if (extractArgs(stack,oper,context,args)) {
|
||||
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
||||
if (op && op->isInteger())
|
||||
offs = op->number();
|
||||
op = static_cast<ExpOperation*>(args[1]);
|
||||
if (op && op->isInteger()) {
|
||||
len = op->number();
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(str->substr(offs,len)));
|
||||
return true;
|
||||
}
|
||||
if (name == YSTRING("match")) {
|
||||
ObjList args;
|
||||
String buf(*str);
|
||||
if (extractArgs(stack,oper,context,args)) {
|
||||
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
||||
ExpWrapper* wrap = YOBJECT(ExpWrapper,op);
|
||||
JsRegExp* rexp = YOBJECT(JsRegExp,wrap);
|
||||
bool ok = false;
|
||||
if (rexp)
|
||||
ok = buf.matches(rexp->regexp());
|
||||
else if (!wrap) {
|
||||
Regexp r(*static_cast<String*>(op),true);
|
||||
ok = buf.matches(r);
|
||||
}
|
||||
if (ok) {
|
||||
JsArray* jsa = new JsArray(mutex());
|
||||
for (int i = 0; i <= buf.matchCount(); i++)
|
||||
jsa->push(new ExpOperation(buf.matchString(i)));
|
||||
jsa->params().addParam(new ExpOperation((long int)buf.matchOffset(),"index"));
|
||||
if (rexp)
|
||||
jsa->params().addParam(wrap->clone("input"));
|
||||
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ExpEvaluator::pushOne(stack,s_null.ExpOperation::clone());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JsContext::runStringField(GenObject* obj, const String& name, ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
const String* s = YOBJECT(String,obj);
|
||||
if (!s)
|
||||
return false;
|
||||
if (name == YSTRING("length")) {
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation((long int)s->length()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JsContext::runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(DebugAll,"JsContext::runAssign '%s'='%s' [%p]",oper.name().c_str(),oper.c_str(),this);
|
||||
|
|
|
@ -123,26 +123,33 @@ static void dumpRecursiveObj(const GenObject* obj, String& buf, unsigned int dep
|
|||
buf.append(str,"\r\n");
|
||||
return;
|
||||
}
|
||||
seen.append(obj)->setDelete(false);
|
||||
const NamedString* nstr = YOBJECT(NamedString,obj);
|
||||
const NamedPointer* nptr = YOBJECT(NamedPointer,nstr);
|
||||
const char* type = nstr ? (nptr ? "NamedPointer" : "NamedString") : "???";
|
||||
const ScriptContext* scr = YOBJECT(ScriptContext,obj);
|
||||
const ExpWrapper* wrap = 0;
|
||||
bool objRecursed = false;
|
||||
if (scr) {
|
||||
if (YOBJECT(JsObject,scr)) {
|
||||
const JsObject* jso = YOBJECT(JsObject,scr);
|
||||
if (jso) {
|
||||
objRecursed = (seen.find(jso) != 0);
|
||||
if ((jso != obj) && !objRecursed)
|
||||
seen.append(jso)->setDelete(false);
|
||||
if (YOBJECT(JsArray,scr))
|
||||
type = "JsArray";
|
||||
else if (YOBJECT(JsFunction,scr))
|
||||
type = "JsFunction";
|
||||
else if (YOBJECT(JsRegExp,scr))
|
||||
type = "JsRegExp";
|
||||
else
|
||||
type = "JsObject";
|
||||
}
|
||||
else
|
||||
type = "ScriptContext";
|
||||
}
|
||||
seen.append(obj)->setDelete(false);
|
||||
const ExpOperation* exp = YOBJECT(ExpOperation,nstr);
|
||||
if (exp) {
|
||||
if (exp && !scr) {
|
||||
if ((wrap = YOBJECT(ExpWrapper,exp)))
|
||||
type = wrap->object() ? "ExpWrapper" : "Undefined";
|
||||
else if (YOBJECT(ExpFunction,exp))
|
||||
|
@ -155,7 +162,11 @@ static void dumpRecursiveObj(const GenObject* obj, String& buf, unsigned int dep
|
|||
else
|
||||
str << "'" << obj->toString() << "'";
|
||||
str << " (" << type << ")";
|
||||
if (objRecursed)
|
||||
str << " (already seen)";
|
||||
buf.append(str,"\r\n");
|
||||
if (objRecursed)
|
||||
return;
|
||||
str.clear();
|
||||
if (scr) {
|
||||
NamedIterator iter(scr->params());
|
||||
|
@ -309,7 +320,9 @@ ExpOperation* JsObject::popValue(ObjList& stack, GenObject* context)
|
|||
ExpOperation* oper = ExpEvaluator::popOne(stack);
|
||||
if (!oper || (oper->opcode() != ExpEvaluator::OpcField))
|
||||
return oper;
|
||||
bool ok = runField(stack,*oper,context);
|
||||
XDebug(DebugAll,"JsObject::popValue() field '%s' in '%s' [%p]",
|
||||
oper->name().c_str(),toString().c_str(),this);
|
||||
bool ok = runMatchingField(stack,*oper,context);
|
||||
TelEngine::destruct(oper);
|
||||
return ok ? ExpEvaluator::popOne(stack) : 0;
|
||||
}
|
||||
|
|
|
@ -133,6 +133,26 @@ bool ScriptContext::runAssign(ObjList& stack, const ExpOperation& oper, GenObjec
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ScriptContext::runMatchingField(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
ExpExtender* ext = this;
|
||||
if (!hasField(stack,oper,context)) {
|
||||
ext = 0;
|
||||
for (ObjList* l = stack.skipNull(); l; l = l->skipNext()) {
|
||||
ext = YOBJECT(ExpExtender,l->get());
|
||||
if (ext && ext->hasField(stack,oper,context))
|
||||
break;
|
||||
ext = 0;
|
||||
}
|
||||
}
|
||||
if (!ext) {
|
||||
ScriptRun* run = YOBJECT(ScriptRun,context);
|
||||
if (run)
|
||||
ext = run->context();
|
||||
}
|
||||
return ext && ext->runField(stack,oper,context);
|
||||
}
|
||||
|
||||
bool ScriptContext::copyFields(ObjList& stack, const ScriptContext& original, GenObject* context)
|
||||
{
|
||||
bool ok = true;
|
||||
|
|
|
@ -1216,6 +1216,15 @@ public:
|
|||
*/
|
||||
virtual bool copyFields(ObjList& stack, const ScriptContext& original, GenObject* context);
|
||||
|
||||
/**
|
||||
* Try to evaluate a single field searching for a matching context
|
||||
* @param stack Evaluation stack in use, field value must be pushed on it
|
||||
* @param oper Field to evaluate
|
||||
* @param context Pointer to context data passed from evaluation methods
|
||||
* @return True if evaluation succeeded
|
||||
*/
|
||||
bool runMatchingField(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
|
||||
private:
|
||||
NamedList m_params;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue