Ejemplo n.º 1
0
EncodedJSValue JSC_HOST_CALL mapProtoFuncForEach(CallFrame* callFrame)
{
    MapData* data = getMapData(callFrame, callFrame->thisValue());
    if (!data)
        return JSValue::encode(jsUndefined());
    JSValue callBack = callFrame->argument(0);
    CallData callData;
    CallType callType = getCallData(callBack, callData);
    if (callType == CallTypeNone)
        return JSValue::encode(throwTypeError(callFrame, WTF::ASCIILiteral("Map.prototype.forEach called without callback")));
    JSValue thisValue = callFrame->argument(1);
    VM* vm = &callFrame->vm();
    if (callType == CallTypeJS) {
        JSFunction* function = jsCast<JSFunction*>(callBack);
        CachedCall cachedCall(callFrame, function, 2);
        for (auto ptr = data->begin(), end = data->end(); ptr != end && !vm->exception(); ++ptr) {
            cachedCall.setThis(thisValue);
            cachedCall.setArgument(0, ptr.value());
            cachedCall.setArgument(1, ptr.key());
            cachedCall.call();
        }
    } else {
        for (auto ptr = data->begin(), end = data->end(); ptr != end && !vm->exception(); ++ptr) {
            MarkedArgumentBuffer args;
            args.append(ptr.value());
            args.append(ptr.key());
            JSC::call(callFrame, callBack, callType, callData, thisValue, args);
        }
    }
    return JSValue::encode(jsUndefined());
}
Ejemplo n.º 2
0
EncodedJSValue JSC_HOST_CALL mapProtoFuncForEach(CallFrame* callFrame)
{
    JSMap* map = getMap(callFrame, callFrame->thisValue());
    if (!map)
        return JSValue::encode(jsUndefined());
    JSValue callBack = callFrame->argument(0);
    CallData callData;
    CallType callType = getCallData(callBack, callData);
    if (callType == CallTypeNone)
        return JSValue::encode(throwTypeError(callFrame, WTF::ASCIILiteral("Map.prototype.forEach called without callback")));
    JSValue thisValue = callFrame->argument(1);
    VM* vm = &callFrame->vm();
    JSMapIterator* iterator = JSMapIterator::create(*vm, callFrame->callee()->globalObject()->mapIteratorStructure(), map, MapIterateKeyValue);
    JSValue key, value;
    if (callType == CallTypeJS) {
        JSFunction* function = jsCast<JSFunction*>(callBack);
        CachedCall cachedCall(callFrame, function, 3);
        while (iterator->nextKeyValue(key, value) && !vm->exception()) {
            cachedCall.setThis(thisValue);
            cachedCall.setArgument(0, value);
            cachedCall.setArgument(1, key);
            cachedCall.setArgument(2, map);
            cachedCall.call();
        }
        iterator->finish();
    } else {
        while (iterator->nextKeyValue(key, value) && !vm->exception()) {
            MarkedArgumentBuffer args;
            args.append(value);
            args.append(key);
            args.append(map);
            JSC::call(callFrame, callBack, callType, callData, thisValue, args);
        }
        iterator->finish();
    }
    return JSValue::encode(jsUndefined());
}
Ejemplo n.º 3
0
JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    JSString* sourceVal = thisValue.toThisJSString(exec);
    const UString& source = sourceVal->value();

    JSValue pattern = args.at(0);

    JSValue replacement = args.at(1);
    UString replacementString;
    CallData callData;
    CallType callType = replacement.getCallData(callData);
    if (callType == CallTypeNone)
        replacementString = replacement.toString(exec);

    if (pattern.isObject(&RegExpObject::info)) {
        RegExp* reg = asRegExpObject(pattern)->regExp();
        bool global = reg->global();

        RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();

        int lastIndex = 0;
        int startPosition = 0;

        Vector<UString::Range, 16> sourceRanges;
        Vector<UString, 16> replacements;

        // This is either a loop (if global is set) or a one-way (if not).
        if (global && callType == CallTypeJS) {
            // reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue
            int argCount = reg->numSubpatterns() + 1 + 2;
            JSFunction* func = asFunction(replacement);
            CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot());
            if (exec->hadException())
                return jsNull();
            while (true) {
                int matchIndex;
                int matchLen;
                int* ovector;
                regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
                if (matchIndex < 0)
                    break;
                
                sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));

                int completeMatchStart = ovector[0];
                unsigned i = 0;
                for (; i < reg->numSubpatterns() + 1; ++i) {
                    int matchStart = ovector[i * 2];
                    int matchLen = ovector[i * 2 + 1] - matchStart;

                    if (matchStart < 0)
                        cachedCall.setArgument(i, jsUndefined());
                    else
                        cachedCall.setArgument(i, jsSubstring(exec, source, matchStart, matchLen));
                }

                cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart));
                cachedCall.setArgument(i++, sourceVal);
                
                cachedCall.setThis(exec->globalThisValue());
                replacements.append(cachedCall.call().toString(cachedCall.newCallFrame()));
                if (exec->hadException())
                    break;

                lastIndex = matchIndex + matchLen;
                startPosition = lastIndex;

                // special case of empty match
                if (matchLen == 0) {
                    startPosition++;
                    if (startPosition > source.size())
                        break;
                }
            }            
        } else {
            do {
                int matchIndex;
                int matchLen;
                int* ovector;
                regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
                if (matchIndex < 0)
                    break;

                sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));

                if (callType != CallTypeNone) {
                    int completeMatchStart = ovector[0];
                    MarkedArgumentBuffer args;

                    for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) {
                        int matchStart = ovector[i * 2];
                        int matchLen = ovector[i * 2 + 1] - matchStart;

                        if (matchStart < 0)
                            args.append(jsUndefined());
                        else
                            args.append(jsSubstring(exec, source, matchStart, matchLen));
                    }

                    args.append(jsNumber(exec, completeMatchStart));
                    args.append(sourceVal);

                    replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec));
                    if (exec->hadException())
                        break;
                } else
                    replacements.append(substituteBackreferences(replacementString, source, ovector, reg));

                lastIndex = matchIndex + matchLen;
                startPosition = lastIndex;

                // special case of empty match
                if (matchLen == 0) {
                    startPosition++;
                    if (startPosition > source.size())
                        break;
                }
            } while (global);
        }

        if (!lastIndex && replacements.isEmpty())
            return sourceVal;

        if (lastIndex < source.size())
            sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));

        return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(),
            replacements.data(), replacements.size()));
    }

    // Not a regular expression, so treat the pattern as a string.

    UString patternString = pattern.toString(exec);
    int matchPos = source.find(patternString);

    if (matchPos == -1)
        return sourceVal;

    int matchLen = patternString.size();
    if (callType != CallTypeNone) {
        MarkedArgumentBuffer args;
        args.append(jsSubstring(exec, source, matchPos, matchLen));
        args.append(jsNumber(exec, matchPos));
        args.append(sourceVal);

        replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec);
    }

    int ovector[2] = { matchPos, matchPos + matchLen };
    return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0)));
}