Пример #1
0
SerializationReturnCode CloneSerializer::serialize(JSValue in)
{
    Vector<uint32_t, 16> indexStack;
    Vector<uint32_t, 16> lengthStack;
    Vector<PropertyNameArray, 16> propertyStack;
    Vector<JSObject*, 16> inputObjectStack;
    Vector<JSArray*, 16> inputArrayStack;
    Vector<WalkerState, 16> stateStack;
    WalkerState state = StateUnknown;
    JSValue inValue = in;
    unsigned tickCount = ticksUntilNextCheck();
    while (1) {
        switch (state) {
            arrayStartState:
            case ArrayStartState: {
                ASSERT(isArray(inValue));
                if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion)
                    return StackOverflowError;

                JSArray* inArray = asArray(inValue);
                unsigned length = inArray->length();
                if (!startArray(inArray))
                    break;
                inputArrayStack.append(inArray);
                indexStack.append(0);
                lengthStack.append(length);
                // fallthrough
            }
            arrayStartVisitMember:
            case ArrayStartVisitMember: {
                if (!--tickCount) {
                    if (didTimeOut())
                        return InterruptedExecutionError;
                    tickCount = ticksUntilNextCheck();
                }

                JSArray* array = inputArrayStack.last();
                uint32_t index = indexStack.last();
                if (index == lengthStack.last()) {
                    endObject();
                    inputArrayStack.removeLast();
                    indexStack.removeLast();
                    lengthStack.removeLast();
                    break;
                }
                if (array->canGetIndex(index))
                    inValue = array->getIndex(index);
                else {
                    bool hasIndex = false;
                    inValue = getSparseIndex(array, index, hasIndex);
                    if (!hasIndex) {
                        indexStack.last()++;
                        goto arrayStartVisitMember;
                    }
                }

                write(index);
                if (dumpIfTerminal(inValue)) {
                    indexStack.last()++;
                    goto arrayStartVisitMember;
                }
                stateStack.append(ArrayEndVisitMember);
                goto stateUnknown;
            }
            case ArrayEndVisitMember: {
                indexStack.last()++;
                goto arrayStartVisitMember;
            }
            objectStartState:
            case ObjectStartState: {
                ASSERT(inValue.isObject());
                if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion)
                    return StackOverflowError;
                JSObject* inObject = asObject(inValue);
                if (!startObject(inObject))
                    break;
                inputObjectStack.append(inObject);
                indexStack.append(0);
                propertyStack.append(PropertyNameArray(m_exec));
                inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
                // fallthrough
            }
            objectStartVisitMember:
            case ObjectStartVisitMember: {
                if (!--tickCount) {
                    if (didTimeOut())
                        return InterruptedExecutionError;
                    tickCount = ticksUntilNextCheck();
                }

                JSObject* object = inputObjectStack.last();
                uint32_t index = indexStack.last();
                PropertyNameArray& properties = propertyStack.last();
                if (index == properties.size()) {
                    endObject();
                    inputObjectStack.removeLast();
                    indexStack.removeLast();
                    propertyStack.removeLast();
                    break;
                }
                inValue = getProperty(object, properties[index]);
                if (shouldTerminate())
                    return ExistingExceptionError;

                if (!inValue) {
                    // Property was removed during serialisation
                    indexStack.last()++;
                    goto objectStartVisitMember;
                }
                write(properties[index]);

                if (shouldTerminate())
                    return ExistingExceptionError;

                if (!dumpIfTerminal(inValue)) {
                    stateStack.append(ObjectEndVisitMember);
                    goto stateUnknown;
                }
                // fallthrough
            }
            case ObjectEndVisitMember: {
                if (shouldTerminate())
                    return ExistingExceptionError;

                indexStack.last()++;
                goto objectStartVisitMember;
            }
            stateUnknown:
            case StateUnknown:
                if (dumpIfTerminal(inValue))
                    break;

                if (isArray(inValue))
                    goto arrayStartState;
                goto objectStartState;
        }
        if (stateStack.isEmpty())
            break;

        state = stateStack.last();
        stateStack.removeLast();

        if (!--tickCount) {
            if (didTimeOut())
                return InterruptedExecutionError;
            tickCount = ticksUntilNextCheck();
        }
    }
    if (m_failed)
        return UnspecifiedError;

    return SuccessfullyCompleted;
}
Пример #2
0
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
{
    JSValue thisValue = exec->hostThisValue();
    bool isRealArray = isJSArray(&exec->globalData(), thisValue);
    if (!isRealArray && !thisValue.inherits(&JSArray::info))
        return throwVMTypeError(exec);
    JSArray* thisObj = asArray(thisValue);
    
    HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
    if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) {
        if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth)
            return throwVMError(exec, createStackOverflowError(exec));
    }

    bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
    if (alreadyVisited)
        return JSValue::encode(jsEmptyString(exec)); // return an empty string, avoiding infinite recursion.

//FYWEBKITMOD begin: setting up StringJoiner (while integrating r148721 due to fix of bug 114779). But not using 'ConstructFromLiteral' optimization which we dont have in our webkit.
    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

	//WebCore::String separator(",", WebCore::String::ConstructFromLiteral);
	//JSStringJoiner stringJoiner(separator, length);
	JSStringJoiner stringJoiner(",", length);
//FYWEBKITMOD end
    unsigned totalSize = length ? length - 1 : 0;
    Vector<RefPtr<UString::Rep>, 256> strBuffer(length);
    for (unsigned k = 0; k < length; k++) {
        JSValue element;
        if (isRealArray && thisObj->canGetIndex(k))
            element = thisObj->getIndex(k);
        else {
            element = thisObj->get(exec, k);
//FYWEBKITMOD begin: added while integrating r148721 due to fix of bug 114779
			if (exec->hadException()) 
				return JSValue::encode(jsUndefined());
//FYWEBKITMOD end
			}
        
//FYWEBKITMOD begin: removed (USE_FIX 1) old implementation which joined the strings manually and added usage of JSStringJoiner (while integrating r148721 due to fix of bug 114779)
#define USE_FIX 1 //keep this defined!!!
#ifdef USE_FIX
		if (element.isUndefinedOrNull()) 
			stringJoiner.append(WebCore::String()); //FYWEBKITMOD: 
		else
			stringJoiner.append(element.toString(exec).rep()); //FYWEBKITMOD: using toString() instead of new toWTFString(). Only difference is an optimization used in the toWTFString() case.

		if (exec->hadException())
			return JSValue::encode(jsUndefined());
		}

	arrayVisitedElements.remove(thisObj);

	return JSValue::encode(stringJoiner.build(exec));

#else
        if (element.isUndefinedOrNull())
            continue;
        
        UString str = element.toString(exec);
        strBuffer[k] = str.rep();
        totalSize += str.size();
        
        if (!strBuffer.data()) {
            throwOutOfMemoryError(exec);
        }
        
        if (exec->hadException())
            break;
    }