Fixed prototypal inheritance and constructors.
Fixed Array length - it's a property not a method. git-svn-id: http://voip.null.ro/svn/yate@5059 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
57577ceb53
commit
9a805ea5a3
|
@ -53,7 +53,6 @@ public:
|
|||
{
|
||||
params().addParam(new ExpFunction("push"));
|
||||
params().addParam(new ExpFunction("pop"));
|
||||
params().addParam(new ExpFunction("length"));
|
||||
params().addParam(new ExpFunction("concat"));
|
||||
params().addParam(new ExpFunction("join"));
|
||||
params().addParam(new ExpFunction("reverse"));
|
||||
|
@ -62,13 +61,21 @@ public:
|
|||
params().addParam(new ExpFunction("slice"));
|
||||
params().addParam(new ExpFunction("splice"));
|
||||
params().addParam(new ExpFunction("sort"));
|
||||
params().addParam("length","0");
|
||||
}
|
||||
inline long length()
|
||||
{ return m_length; }
|
||||
inline void setLength()
|
||||
{ params().setParam("length",String((int)m_length)); }
|
||||
inline void setLength(long len)
|
||||
{ m_length = len; params().setParam("length",String((int)len)); }
|
||||
|
||||
protected:
|
||||
inline JsArray(Mutex* mtx, const char* name)
|
||||
: JsObject(mtx,name), m_length(0)
|
||||
{ }
|
||||
virtual JsObject* clone(const char* name) const
|
||||
{ return new JsArray(mutex(),name); }
|
||||
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
private:
|
||||
bool runNativeSlice(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
|
@ -85,7 +92,6 @@ public:
|
|||
inline JsObjectObj(Mutex* mtx)
|
||||
: JsObject("Object",mtx,true)
|
||||
{
|
||||
params().addParam(new ExpFunction("constructor"));
|
||||
}
|
||||
protected:
|
||||
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
|
@ -120,6 +126,11 @@ public:
|
|||
params().addParam(new ExpFunction("getUTCSeconds"));
|
||||
}
|
||||
protected:
|
||||
inline JsDate(Mutex* mtx, const char* name)
|
||||
: JsObject(mtx,name)
|
||||
{ }
|
||||
virtual JsObject* clone(const char* name) const
|
||||
{ return new JsDate(mutex(),name); }
|
||||
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
};
|
||||
|
||||
|
@ -148,6 +159,14 @@ static inline void addObject(NamedList& params, const char* name, JsObject* obj)
|
|||
params.addParam(new NamedPointer(name,obj,obj->toString()));
|
||||
}
|
||||
|
||||
// Helper function that adds a constructor to a parent
|
||||
static inline void addConstructor(NamedList& params, const char* name, JsObject* obj)
|
||||
{
|
||||
JsFunction* ctr = new JsFunction(obj->mutex(),name);
|
||||
ctr->params().addParam(new NamedPointer("prototype",obj,obj->toString()));
|
||||
params.addParam(new NamedPointer(name,ctr,ctr->toString()));
|
||||
}
|
||||
|
||||
// Helper function that pops arguments off a stack to a list in proper order
|
||||
static int extractArgs(JsObject* obj, ObjList& stack, const ExpOperation& oper, GenObject* context, ObjList& arguments)
|
||||
{
|
||||
|
@ -173,6 +192,14 @@ JsObject::JsObject(const char* name, Mutex* mtx, bool frozen)
|
|||
params().addParam(new ExpFunction("hasOwnProperty"));
|
||||
}
|
||||
|
||||
JsObject::JsObject(Mutex* mtx, const char* name, bool frozen)
|
||||
: ScriptContext(name),
|
||||
m_frozen(frozen), m_mutex(mtx)
|
||||
{
|
||||
XDebug(DebugAll,"JsObject::JsObject(%p,'%s',%s) [%p]",
|
||||
mtx,name,String::boolText(frozen),this);
|
||||
}
|
||||
|
||||
JsObject::~JsObject()
|
||||
{
|
||||
XDebug(DebugAll,"JsObject::~JsObject '%s' [%p]",toString().c_str(),this);
|
||||
|
@ -191,11 +218,6 @@ bool JsObject::runFunction(ObjList& stack, const ExpOperation& oper, GenObject*
|
|||
JsFunction* jf = YOBJECT(JsFunction,param);
|
||||
if (jf)
|
||||
return jf->runDefined(stack,oper,context);
|
||||
JsObject* jso = YOBJECT(JsObject,param);
|
||||
if (jso) {
|
||||
ExpFunction op("constructor",oper.number());
|
||||
return jso->runFunction(stack,op,context);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -303,13 +325,13 @@ void JsObject::initialize(ScriptContext* context)
|
|||
NamedList& p = context->params();
|
||||
static_cast<String&>(p) = "[Object Global]";
|
||||
if (!p.getParam(YSTRING("Object")))
|
||||
addObject(p,"Object",new JsObjectObj(mtx));
|
||||
addConstructor(p,"Object",new JsObjectObj(mtx));
|
||||
if (!p.getParam(YSTRING("Function")))
|
||||
addObject(p,"Function",new JsFunction(mtx));
|
||||
addConstructor(p,"Function",new JsFunction(mtx));
|
||||
if (!p.getParam(YSTRING("Array")))
|
||||
addObject(p,"Array",new JsArray(mtx));
|
||||
addConstructor(p,"Array",new JsArray(mtx));
|
||||
if (!p.getParam(YSTRING("Date")))
|
||||
addObject(p,"Date",new JsDate(mtx));
|
||||
addConstructor(p,"Date",new JsDate(mtx));
|
||||
if (!p.getParam(YSTRING("Math")))
|
||||
addObject(p,"Math",new JsMath(mtx));
|
||||
}
|
||||
|
@ -327,6 +349,8 @@ bool JsObjectObj::runNative(ObjList& stack, const ExpOperation& oper, GenObject*
|
|||
|
||||
bool JsArray::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(DebugAll,"JsArray::runNative() '%s' in '%s' [%p]",
|
||||
oper.name().c_str(),toString().c_str(),this);
|
||||
if (oper.name() == YSTRING("push")) {
|
||||
// Adds one or more elements to the end of an array and returns the new length of the array.
|
||||
if (!oper.number())
|
||||
|
@ -344,6 +368,7 @@ bool JsArray::runNative(ObjList& stack, const ExpOperation& oper, GenObject* con
|
|||
TelEngine::destruct(op);
|
||||
}
|
||||
m_length += oper.number();
|
||||
setLength();
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(length()));
|
||||
}
|
||||
else if (oper.name() == YSTRING("pop")) {
|
||||
|
@ -368,6 +393,7 @@ bool JsArray::runNative(ObjList& stack, const ExpOperation& oper, GenObject* con
|
|||
}
|
||||
// clear last
|
||||
params().clearParam(last);
|
||||
setLength();
|
||||
}
|
||||
else if (oper.name() == YSTRING("length")) {
|
||||
// Reflects the number of elements in an array.
|
||||
|
@ -624,6 +650,8 @@ bool JsArray::runNativeSort(ObjList& stack, const ExpOperation& oper, GenObject*
|
|||
|
||||
bool JsMath::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(DebugAll,"JsMath::runNative() '%s' in '%s' [%p]",
|
||||
oper.name().c_str(),toString().c_str(),this);
|
||||
if (oper.name() == YSTRING("abs")) {
|
||||
if (!oper.number())
|
||||
return false;
|
||||
|
@ -670,6 +698,8 @@ bool JsMath::runNative(ObjList& stack, const ExpOperation& oper, GenObject* cont
|
|||
|
||||
bool JsDate::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(DebugAll,"JsDate::runNative() '%s' in '%s' [%p]",
|
||||
oper.name().c_str(),toString().c_str(),this);
|
||||
if (oper.name() == YSTRING("now")) {
|
||||
// Returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation((long int)Time::msecNow())); // should check conversion from u_int64_t
|
||||
|
@ -783,6 +813,17 @@ bool JsDate::runNative(ObjList& stack, const ExpOperation& oper, GenObject* cont
|
|||
|
||||
JsFunction::JsFunction(Mutex* mtx)
|
||||
: JsObject("Function",mtx,true)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
JsFunction::JsFunction(Mutex* mtx, const char* name)
|
||||
: JsObject(mtx,String("[function ") + name + "()]",true)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void JsFunction::init()
|
||||
{
|
||||
params().addParam(new ExpFunction("apply"));
|
||||
params().addParam(new ExpFunction("call"));
|
||||
|
@ -790,6 +831,8 @@ JsFunction::JsFunction(Mutex* mtx)
|
|||
|
||||
bool JsFunction::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
XDebug(DebugAll,"JsFunction::runNative() '%s' in '%s' [%p]",
|
||||
oper.name().c_str(),toString().c_str(),this);
|
||||
if (oper.name() == YSTRING("apply")) {
|
||||
// func.apply(new_this,["array","of","params",...])
|
||||
if (oper.number() != 2)
|
||||
|
@ -807,7 +850,15 @@ bool JsFunction::runNative(ObjList& stack, const ExpOperation& oper, GenObject*
|
|||
|
||||
bool JsFunction::runDefined(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
return false;
|
||||
XDebug(DebugAll,"JsObject::runDefined() in '%s' [%p]",toString().c_str(),this);
|
||||
JsObject* proto = YOBJECT(JsObject,getField(stack,"prototype",context));
|
||||
if (proto) {
|
||||
// found prototype, build object
|
||||
JsObject* obj = proto->clone();
|
||||
obj->copyFields(stack,*proto,context);
|
||||
ExpEvaluator::pushOne(stack,new ExpWrapper(obj,oper.name()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
|
|
|
@ -131,6 +131,32 @@ bool ScriptContext::runAssign(ObjList& stack, const ExpOperation& oper, GenObjec
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ScriptContext::copyFields(ObjList& stack, const ScriptContext& original, GenObject* context)
|
||||
{
|
||||
bool ok = true;
|
||||
unsigned int n = original.params().length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
const NamedString* p = original.params().getParam(i);
|
||||
if (!p)
|
||||
continue;
|
||||
NamedString* fld = original.getField(stack, p->name(),context);
|
||||
if (fld) {
|
||||
ExpOperation* op = YOBJECT(ExpOperation,fld);
|
||||
XDebug(DebugAll,"Field '%s' is %s",fld->name().c_str(),
|
||||
(op ? (YOBJECT(ExpFunction,op) ? "function" :
|
||||
(YOBJECT(ExpWrapper,op) ? "object" : "operation")) : "string"));
|
||||
if (op)
|
||||
ok = runAssign(stack, *op, context) && ok;
|
||||
else
|
||||
ok = runAssign(stack, ExpOperation(*fld,fld->name()), context) && ok;
|
||||
}
|
||||
else
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
#define MAKE_NAME(x) { #x, ScriptRun::x }
|
||||
static const TokenDict s_states[] = {
|
||||
MAKE_NAME(Invalid),
|
||||
|
|
|
@ -1099,6 +1099,15 @@ public:
|
|||
*/
|
||||
virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
|
||||
/**
|
||||
* Copy all fields from another context
|
||||
* @param stack Evaluation stack in use
|
||||
* @param original Script context to copy from
|
||||
* @param context Pointer to context data passed from evaluation methods
|
||||
* @return True if all fields were copied
|
||||
*/
|
||||
virtual bool copyFields(ObjList& stack, const ScriptContext& original, GenObject* context);
|
||||
|
||||
private:
|
||||
NamedList m_params;
|
||||
};
|
||||
|
@ -1391,6 +1400,21 @@ public:
|
|||
virtual Mutex* mutex()
|
||||
{ return m_mutex; }
|
||||
|
||||
/**
|
||||
* Clone and rename method
|
||||
* @param name Name of the cloned object
|
||||
* @return New object instance
|
||||
*/
|
||||
virtual JsObject* clone(const char* name) const
|
||||
{ return new JsObject(m_mutex,name); }
|
||||
|
||||
/**
|
||||
* Clone method
|
||||
* @return New object instance
|
||||
*/
|
||||
inline JsObject* clone() const
|
||||
{ return clone(toString()); }
|
||||
|
||||
/**
|
||||
* Try to evaluate a single method
|
||||
* @param stack Evaluation stack in use, parameters are popped off this stack
|
||||
|
@ -1447,6 +1471,14 @@ public:
|
|||
static void initialize(ScriptContext* context);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor for an empty object
|
||||
* @param mtx Pointer to the mutex that serializes this object
|
||||
* @param name Full name of the object
|
||||
* @param frozen True if the object is to be frozen from creation
|
||||
*/
|
||||
JsObject(Mutex* mtx, const char* name, bool frozen = false);
|
||||
|
||||
/**
|
||||
* Try to evaluate a single native method
|
||||
* @param stack Evaluation stack in use, parameters are popped off this stack
|
||||
|
@ -1457,6 +1489,13 @@ protected:
|
|||
*/
|
||||
virtual bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
|
||||
/**
|
||||
* Retrieve the Mutex object used to serialize object access
|
||||
* @return Pointer to the mutex of the context this object belongs to
|
||||
*/
|
||||
inline Mutex* mutex() const
|
||||
{ return m_mutex; }
|
||||
|
||||
private:
|
||||
bool m_frozen;
|
||||
Mutex* m_mutex;
|
||||
|
@ -1477,6 +1516,13 @@ public:
|
|||
*/
|
||||
JsFunction(Mutex* mtx = 0);
|
||||
|
||||
/**
|
||||
* Constructor with function name
|
||||
* @param mtx Pointer to the mutex that serializes this object
|
||||
* @param name Name of the function
|
||||
*/
|
||||
JsFunction(Mutex* mtx, const char* name);
|
||||
|
||||
/**
|
||||
* Try to evaluate a single user defined method
|
||||
* @param stack Evaluation stack in use, parameters are popped off this stack
|
||||
|
@ -1498,6 +1544,8 @@ protected:
|
|||
*/
|
||||
virtual bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue