Keep the prototype as an internal __proto__ property.

Exclude properties starting with two underlines from iterators.


git-svn-id: http://yate.null.ro/svn/yate/trunk@5131 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2012-06-18 17:17:43 +00:00
parent 9826917545
commit a5a434f6cb
4 changed files with 59 additions and 5 deletions

View File

@ -1770,7 +1770,10 @@ bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, GenObject* c
return gotError("Expecting runtime iterator",oper.lineNumber()); return gotError("Expecting runtime iterator",oper.lineNumber());
} }
bool ok = false; bool ok = false;
const NamedString* n = iter->get(); const NamedString* n;
do {
n = iter->get();
} while (n && n->name().startsWith("__"));
if (n) { if (n) {
static const ExpOperation s_assign(OpcAssign); static const ExpOperation s_assign(OpcAssign);
pushOne(stack,iter->field().clone()); pushOne(stack,iter->field().clone());

View File

@ -180,6 +180,8 @@ static void dumpRecursiveObj(const GenObject* obj, String& buf, unsigned int dep
} }
const String JsObject::s_protoName("__proto__");
JsObject::JsObject(const char* name, Mutex* mtx, bool frozen) JsObject::JsObject(const char* name, Mutex* mtx, bool frozen)
: ScriptContext(String("[object ") + name + "]"), : ScriptContext(String("[object ") + name + "]"),
m_frozen(frozen), m_mutex(mtx) m_frozen(frozen), m_mutex(mtx)
@ -226,10 +228,29 @@ JsObject* JsObject::buildCallContext(Mutex* mtx, ExpOperation* thisObj)
return ctxt; return ctxt;
} }
bool JsObject::hasField(ObjList& stack, const String& name, GenObject* context) const
{
if (ScriptContext::hasField(stack,name,context))
return true;
const ScriptContext* proto = YOBJECT(ScriptContext,params().getParam(protoName()));
return proto && proto->hasField(stack,name,context);
}
NamedString* JsObject::getField(ObjList& stack, const String& name, GenObject* context) const
{
NamedString* fld = ScriptContext::getField(stack,name,context);
if (fld)
return fld;
const ScriptContext* proto = YOBJECT(ScriptContext,params().getParam(protoName()));
return proto ? proto->getField(stack,name,context) : 0;
}
JsObject* JsObject::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context) JsObject* JsObject::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
{ {
if (!ref())
return 0;
JsObject* obj = clone(); JsObject* obj = clone();
obj->copyFields(stack,*this,context); obj->params().addParam(new ExpWrapper(this,protoName()));
return obj; return obj;
} }
@ -237,7 +258,7 @@ bool JsObject::runFunction(ObjList& stack, const ExpOperation& oper, GenObject*
{ {
XDebug(DebugInfo,"JsObject::runFunction() '%s' in '%s' [%p]", XDebug(DebugInfo,"JsObject::runFunction() '%s' in '%s' [%p]",
oper.name().c_str(),toString().c_str(),this); oper.name().c_str(),toString().c_str(),this);
NamedString* param = params().getParam(oper.name()); NamedString* param = getField(stack,oper.name(),context);
if (!param) if (!param)
return false; return false;
ExpFunction* ef = YOBJECT(ExpFunction,param); ExpFunction* ef = YOBJECT(ExpFunction,param);
@ -253,7 +274,7 @@ bool JsObject::runField(ObjList& stack, const ExpOperation& oper, GenObject* con
{ {
XDebug(DebugAll,"JsObject::runField() '%s' in '%s' [%p]", XDebug(DebugAll,"JsObject::runField() '%s' in '%s' [%p]",
oper.name().c_str(),toString().c_str(),this); oper.name().c_str(),toString().c_str(),this);
const String* param = params().getParam(oper.name()); const String* param = getField(stack,oper.name(),context);
if (param) { if (param) {
ExpFunction* ef = YOBJECT(ExpFunction,param); ExpFunction* ef = YOBJECT(ExpFunction,param);
if (ef) if (ef)

View File

@ -1588,6 +1588,24 @@ public:
inline JsObject* clone() const inline JsObject* clone() const
{ return clone(toString()); } { return clone(toString()); }
/**
* Check if a certain field is assigned in the object or its prototype
* @param stack Evaluation stack in use
* @param name Name of the field to test
* @param context Pointer to arbitrary object passed from evaluation methods
* @return True if the field is present
*/
virtual bool hasField(ObjList& stack, const String& name, GenObject* context) const;
/**
* Get a pointer to a field in the object or its prototype
* @param stack Evaluation stack in use
* @param name Name of the field to retrieve
* @param context Pointer to arbitrary object passed from evaluation methods
* @return Pointer to field, NULL if not present
*/
virtual NamedString* getField(ObjList& stack, const String& name, GenObject* context) const;
/** /**
* Native constructor initialization, called by addConstructor on the prototype * Native constructor initialization, called by addConstructor on the prototype
* @param construct Function that has this object as prototype * @param construct Function that has this object as prototype
@ -1706,6 +1724,13 @@ public:
*/ */
static void initialize(ScriptContext* context); static void initialize(ScriptContext* context);
/**
* Get the name of the internal property used to track prototypes
* @return The "__proto__" constant string
*/
inline static const String& protoName()
{ return s_protoName; }
/** /**
* Helper method to return the hierarchical structure of an object * Helper method to return the hierarchical structure of an object
* @param obj Object to dump structure * @param obj Object to dump structure
@ -1746,6 +1771,7 @@ protected:
{ return m_mutex; } { return m_mutex; }
private: private:
static const String s_protoName;
bool m_frozen; bool m_frozen;
Mutex* m_mutex; Mutex* m_mutex;
}; };

View File

@ -424,8 +424,12 @@ JsObject* JsMessage::runConstructor(ObjList& stack, const ExpOperation& oper, Ge
ExpOperation* broad = static_cast<ExpOperation*>(args[1]); ExpOperation* broad = static_cast<ExpOperation*>(args[1]);
if (!name) if (!name)
return 0; return 0;
if (!ref())
return 0;
Message* m = new Message(*name,0,broad && broad->valBoolean()); Message* m = new Message(*name,0,broad && broad->valBoolean());
return new JsMessage(m,mutex(),true); JsMessage* obj = new JsMessage(m,mutex(),true);
obj->params().addParam(new ExpWrapper(this,protoName()));
return obj;
} }
void JsMessage::initialize(ScriptContext* context) void JsMessage::initialize(ScriptContext* context)