Example #1
0
    Atom VectorBaseObject::filter(ScriptObject *callback, Atom thisObject)
    {
        AvmCore* core = this->core();
        VectorBaseObject *r = newVector();

        if (!callback)
            return r->atom();

        ScriptObject *d = this;
        uint32 len = m_length;

        for (uint32 i = 0, k = 0; i < len; i++)
        {
            // If thisObject is null, the call function will substitute the global object
            // args are modified in place by callee
            Atom element = d->getUintProperty(i);
            Atom args[4] = {
                thisObject,
                element,
                core->uintToAtom(i), // index
                this->atom()
            };
            Atom result = callback->call(3, args);
            if (result == trueAtom)
                r->setUintProperty(k++, element);
        }

        return r->atom();
    }
	Atom VectorBaseObject::filter(ScriptObject *callback, Atom thisObject)
	{
		AvmCore* core = this->core();
		VectorBaseObject *r = newVector();

		if (!callback)
			return r->atom();

		ScriptObject *d = this;
		uint32 len = m_length;

		// If thisObject is null, the call function will substitute the global object 
		Atom args[4] = { thisObject, nullObjectAtom, nullObjectAtom, this->atom() };

		for (uint32 i = 0, k = 0; i < len; i++)
		{
			args[1] = d->getUintProperty (i); // element
			args[2] = core->uintToAtom (i); // index

			Atom result = callback->call(3, args);

			if (result == trueAtom)
			{
				r->setUintProperty (k++, args[1]);
			}
		}

		return r->atom();
	}
    /**
     * Array.prototype.reverse()
	 * TRANSFERABLE: Needs to support generic objects as well as Array objects
     */
	/*static*/ Atom ArrayClass::generic_reverse(Toplevel* toplevel, Atom thisAtom)
    {
        ArrayObject *a = isArray(toplevel, thisAtom);
	
		if (a && (a->isSimpleDense()))
		{
			a->m_denseArr.reverse();
			return thisAtom;
		}

		// generic object version
		if (!AvmCore::isObject(thisAtom))
			return thisAtom;

		ScriptObject *d = AvmCore::atomToScriptObject(thisAtom);
		uint32 j = getLengthHelper(toplevel, d);

		uint32 i = 0;
		if (j)
			j--;

		while (i < j) {
			Atom frontAtom = d->getUintProperty(i);
			Atom backAtom  = d->getUintProperty(j);

			d->setUintProperty(i++, backAtom);
			d->setUintProperty(j--, frontAtom);
		}

		return thisAtom;
	}
	/**
     * Array.prototype.pop()
	 * TRANSFERABLE: Needs to support generic objects as well as Array objects
     */
	/*static*/ Atom ArrayClass::generic_pop(Toplevel* toplevel, Atom thisAtom)
    {
        ArrayObject *a = isArray(toplevel, thisAtom);

		if (a)
			return a->pop();

		if (!AvmCore::isObject(thisAtom))
			return undefinedAtom;

		// Different than Rhino (because of delete) but matches 262.pdf
		ScriptObject *d = AvmCore::atomToScriptObject(thisAtom);
		uint32 len = getLengthHelper(toplevel, d);
		if (!len)
		{
			setLengthHelper(toplevel, d, 0);
			return undefinedAtom;
		}
		else
		{
			Atom outAtom = d->getUintProperty (len-1); 
			d->delUintProperty (len - 1);
			setLengthHelper(toplevel, d, len - 1);
			return outAtom;
		}
    }
	/**
     * Array.prototype.shift()
	 * TRANSFERABLE: Needs to support generic objects as well as Array objects
     */
	/*static*/ Atom ArrayClass::generic_shift(Toplevel* toplevel, Atom thisAtom)
	{
		ArrayObject *a = isArray(toplevel, thisAtom);

		if (a && a->isSimpleDense())
		{
			if (!a->m_length)
				return undefinedAtom;

			a->m_length--;
			return (a->m_denseArr.shift());
		}

		if (!AvmCore::isObject(thisAtom))
			return undefinedAtom;

		Atom outAtom;
		ScriptObject *d = AvmCore::atomToScriptObject(thisAtom);
		uint32 len = getLengthHelper(toplevel, d);

		if (len == 0)
		{
			// set len to 0 (ecmascript spec)
			setLengthHelper(toplevel, d, 0);
			outAtom = undefinedAtom;
		}
		else
		{
			// Get the 0th element to return
			outAtom = d->getUintProperty(0);

			// Move all of the elements down
			for (uint32 i=0; i<len-1; i++) {
				d->setUintProperty(i, d->getUintProperty(i+1));
			}
			
			d->delUintProperty (len - 1);
			setLengthHelper(toplevel, d, len - 1);
		}

		return outAtom;
	}
    /**
     * Array.prototype.slice()
	 * TRANSFERABLE: Needs to support generic objects as well as Array objects
     */
	/*static*/ ArrayObject* ArrayClass::generic_slice(Toplevel* toplevel, Atom thisAtom, double A, double B)
    {
		if (!AvmCore::isObject(thisAtom))
			return 0;

		ScriptObject *d = AvmCore::atomToScriptObject(thisAtom);
		uint32 len = getLengthHelper(toplevel, d);

		// if a param is passed then the first one is A
		// if no params are passed then A = 0
		uint32 a = NativeObjectHelpers::ClampIndex(A, len);
		uint32 b = NativeObjectHelpers::ClampIndex(B, len);
		if (b < a)
			b = a;

		ArrayObject *out = toplevel->arrayClass->newArray(b-a);

		uint32 outIndex=0;
		for (uint32 i=a; i<b; i++) {
			out->setUintProperty (outIndex++, d->getUintProperty (i));
		}

		return out;
	}
	/**
	15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , 
 ] ] ] )
	When the concat method is called with zero or more arguments item1, item2, etc., it returns an array containing
	the array elements of the object followed by the array elements of each argument in order.
	The following steps are taken:
	1. Let A be a new array created as if by the expression new Array().
	2. Let n be 0.
	3. Let E be this object.
	4. If E is not an Array object, go to step 16.
	5. Let k be 0.
	6. Call the [[Get]] method of E with argument "length".
	7. If k equals Result(6) go to step 19.
	8. Call ToString(k).
	9. If E has a property named by Result(8), go to step 10, 
	but if E has no property named by Result(8), go to step 13.
	10. Call ToString(n).
	11. Call the [[Get]] method of E with argument Result(8).
	12. Call the [[Put]] method of A with arguments Result(10) and Result(11).
	13. Increase n by 1.
	14. Increase k by 1.
	15. Go to step 7.
	16. Call ToString(n).
	17. Call the [[Put]] method of A with arguments Result(16) and E.
	18. Increase n by 1.
	19. Get the next argument in the argument list; if there are no more arguments, go to step 22.
	20. Let E be Result(19).
	21. Go to step 4.
	22. Call the [[Put]] method of A with arguments "length" and n.
	23. Return A.
	The length property of the concat method is 1.
	NOTE The concat function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be
	transferred to other kinds of objects for use as a method. Whether the concat function can be applied successfully to a host
	object is implementation-dependent.
	*/
	/*static*/ ArrayObject* ArrayClass::generic_concat(Toplevel* toplevel, Atom thisAtom, ArrayObject* args)
    {
		AvmCore* core = toplevel->core();
		ScriptObject *d = AvmCore::isObject(thisAtom) ? AvmCore::atomToScriptObject(thisAtom) : 0;
		
		uint32 len = 0;
		if (d)
		{
			len = getLengthHelper(toplevel, d);
		}

        ArrayObject *a = isArray(toplevel, thisAtom);
		uint32 i;

		uint32 argc = args->getLength();

		int  newLength = len;
		for (i = 0; i< argc; i++) 
		{
			Atom atom = args->getUintProperty(i);
			if (AvmCore::istype(atom, ARRAY_TYPE)) 
			{
				ArrayObject *b = (ArrayObject*) AvmCore::atomToScriptObject(atom);
				newLength += b->getLength();
			}
			else
			{
				newLength++;
			}
		}

		ArrayObject *out = toplevel->arrayClass->newArray(newLength);
		int denseLength = 0;
		// Only copy over elements for Arrays, not objects according to spec
		// 4. If E is not an Array object, go to step 16.
		if (a && newLength)
		{
			denseLength = a->getDenseLength();

			// copy over our dense part
			out->m_denseArr.push (&a->m_denseArr);
			out->m_length += denseLength;

			// copy over any non-dense values (or all values if this isn't an array object)
			for (i = denseLength; i < len; i++) {
				out->setUintProperty(i, d->getUintProperty(i));
			}
		}

		for (i = 0; i< (uint32)argc; i++) 
		{
			Atom atom = args->getUintProperty(i);
			if (AvmCore::istype(atom, ARRAY_TYPE)) 
			{
				ArrayObject *b = (ArrayObject*) AvmCore::atomToScriptObject(atom);
				// copy over dense parts
				out->m_denseArr.push (&b->m_denseArr);
				out->m_length += b->getDenseLength();

				// copy over any non-dense values
				uint32 len = b->getLength();
				for (uint32 j=b->getDenseLength(); j<len; j++) {
					out->m_denseArr.push (b->getUintProperty(j));
					out->m_length++;
				}
			}
			else
			{
				out->m_denseArr.push (atom);
				out->m_length++;
			}
		}

		return out;
	}