bool VJSStructuredClone::_IsSerializable (XBOX::VJSValue inValue)
{
	xbox_assert(inValue.IsObject());
	
	XBOX::VJSObject	object	= inValue.GetObject();
	
	if (object.HasProperty("constructorName") && object.GetProperty("constructorName").IsString()
	&& object.HasProperty("serialize") && object.GetProperty("serialize").IsFunction())
		
		return true;
	
	else
		
		return false;
}
static void _AddToList (XBOX::VJSContext &inContext, const XBOX::VString &inConstructorName, XBOX::VJSObject &inConstructedObject)
{
	if (inContext.GetGlobalObject().HasProperty(inConstructorName)) {

		XBOX::VJSObject	workerObject	= inContext.GetGlobalObject().GetPropertyAsObject(inConstructorName);

		if (workerObject.IsObject() && workerObject.HasProperty("list")) {

			XBOX::VJSValue	value	= workerObject.GetProperty("list");

			if (value.IsArray()) {

				XBOX::VJSArray	listArray(value);
				sLONG			i;

				for (i = 0; i < listArray.GetLength(); i++) {

					value = listArray.GetValueAt(i);
					if (value.IsNull()) {

						listArray.SetValueAt(i, inConstructedObject);
						break;

					}	

				}
				if (i == listArray.GetLength()) 

					listArray.PushValue(inConstructedObject);

			} else {

				xbox_assert(false);

			}

		} else {

			xbox_assert(false);

		}
			
	} else {

		xbox_assert(false);

	}
}
USING_TOOLBOX_NAMESPACE

VJSStructuredClone *VJSStructuredClone::RetainClone (XBOX::VJSValue inValue)
{	
	std::map<JS4D::ValueRef, SNode *>	alreadyCreated;
	std::list<SEntry>					toDoList;
	SNode								*root;

	if ((root = _ValueToNode(inValue, &alreadyCreated, &toDoList)) == NULL)

		return NULL;

	while (!toDoList.empty()) {

		// Property iterator will also iterate Array object indexes (they are converted into string).

		XBOX::VJSValue				value(inValue.GetContext(), toDoList.front().fValueRef);
		XBOX::VJSPropertyIterator	i(value.GetObject());
		SNode						*p, *q, *r;

		p = toDoList.front().fNode;
		xbox_assert(p->fType == eNODE_OBJECT || p->fType == eNODE_ARRAY);
		
		toDoList.pop_front();

		// Object or Array with no attributes?

		if (!i.IsValid()) 

			continue;

		// Get prototype and dump its attribute names.

		XBOX::VJSObject	prototypeObject	= value.GetObject().GetPrototype(inValue.GetContext());
		bool			hasPrototype	= prototypeObject.IsObject();

		// Iterate child(s).

		for ( ; i.IsValid(); ++i) {

			XBOX::VString	name;

			i.GetPropertyName(name);
	
			// Check attribute name: If it is part of prototype, do not clone it.

			if (hasPrototype && prototypeObject.HasProperty(name))

				continue;

			value = i.GetProperty();
			if ((r = _ValueToNode(value, &alreadyCreated, &toDoList)) == NULL) 

				break;

			else if (p->fValue.fFirstChild != NULL) 
				
				q->fNextSibling = r;
						
			else
				
				p->fValue.fFirstChild = r;

			r->fName = name;
			q = r;

		}

		if (p->fValue.fFirstChild != NULL) 

			q->fNextSibling = NULL;

		if (i.IsValid()) {

			_FreeNode(root);
			root = NULL;
			break;

		} 	

	}

	if (root != NULL) {

		VJSStructuredClone	*structuredClone;

		if ((structuredClone = new VJSStructuredClone()) != NULL)

			structuredClone->fRoot = root;

		else

			_FreeNode(root);

		return structuredClone;

	} else

		return NULL;
}