示例#1
0
UString FunctionExecutable::paramString() const
{
    FunctionParameters& parameters = *m_parameters;
    UStringBuilder builder;
    for (size_t pos = 0; pos < parameters.size(); ++pos) {
        if (!builder.isEmpty())
            builder.append(", ");
        builder.append(parameters[pos].ustring());
    }
    return builder.toUString();
}
static RegExp* parseRegExpLine(JSGlobalData& globalData, char* line, int lineLength)
{
    UStringBuilder pattern;
    
    if (line[0] != '/')
        return 0;

    int i = scanString(line + 1, lineLength - 1, pattern, '/') + 1;

    if ((i >= lineLength) || (line[i] != '/'))
        return 0;

    ++i;

    return RegExp::create(globalData, pattern.toUString(), regExpFlags(line + i));
}
示例#3
0
Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
{
    JSObject* object = constructEmptyObject(m_exec);
    if (m_exec->hadException())
        return Local<Unknown>(m_exec->globalData(), jsNull());

    PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier);
    object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value.get());

    UStringBuilder result;
    if (appendStringifiedValue(result, value.get(), object, emptyPropertyName) != StringifySucceeded)
        return Local<Unknown>(m_exec->globalData(), jsUndefined());
    if (m_exec->hadException())
        return Local<Unknown>(m_exec->globalData(), jsNull());

    return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toUString()));
}
// ECMA 15.3.2 The Function Constructor
JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
{
    // Functions need to have a space following the opening { due to for web compatibility
    // see https://bugs.webkit.org/show_bug.cgi?id=24350
    // We also need \n before the closing } to handle // comments at the end of the last line
    UString program;
    if (args.isEmpty())
        program = "(function() { \n})";
    else if (args.size() == 1)
        program = makeUString("(function() { ", args.at(0).toString(exec), "\n})");
    else {
        UStringBuilder builder;
        builder.append("(function(");
        builder.append(args.at(0).toString(exec));
        for (size_t i = 1; i < args.size() - 1; i++) {
            builder.append(",");
            builder.append(args.at(i).toString(exec));
        }
        builder.append(") { ");
        builder.append(args.at(args.size() - 1).toString(exec));
        builder.append("\n})");
        program = builder.toUString();
    }

    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
    JSGlobalData& globalData = globalObject->globalData();
    SourceCode source = makeSource(program, sourceURL, lineNumber);
    JSObject* exception = 0;
    RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
    if (!function) {
        ASSERT(exception);
        return throwError(exec, exception);
    }

    ScopeChain scopeChain(globalObject, &globalData, globalObject, exec->globalThisValue());
    return new (exec) JSFunction(exec, function, scopeChain.node());
}
示例#5
0
JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
{
    UString pattern = asRegExpObject(slotBase)->regExp()->pattern();

    size_t forwardSlashPosition = pattern.find('/');
    if (forwardSlashPosition == notFound)
        return jsString(exec, pattern);

    // 'completed' tracks the length of original pattern already copied
    // into the result buffer.
    size_t completed = 0;
    UStringBuilder result;

    do {
        // 'slashesPosition' points to the first (of possibly zero) backslash
        // prior to the forwards slash.
        size_t slashesPosition = forwardSlashPosition;
        while (slashesPosition && pattern[slashesPosition - 1] == '\\')
            --slashesPosition;

        // Check whether the number of backslashes is odd or even -
        // if odd, the forwards slash is already escaped, so we mustn't
        // double escape it.
        if ((forwardSlashPosition - slashesPosition) & 1)
            result.append(pattern.substringSharingImpl(completed, forwardSlashPosition - completed + 1));
        else {
            result.append(pattern.substringSharingImpl(completed, forwardSlashPosition - completed));
            result.append("\\/");
        }
        completed = forwardSlashPosition + 1;

        forwardSlashPosition = pattern.find('/', completed);
    } while (forwardSlashPosition != notFound);

    // Copy in the remainder of the pattern to the buffer.
    result.append(pattern.substringSharingImpl(completed));
    return jsString(exec, result.toUString());
}
static RegExpTest* parseTestLine(char* line, int lineLength)
{
    UStringBuilder subjectString;
    
    if ((line[0] != ' ') || (line[1] != '"'))
        return 0;

    int i = scanString(line + 2, lineLength - 2, subjectString, '"') + 2;

    if ((i >= (lineLength - 2)) || (line[i] != '"') || (line[i+1] != ',') || (line[i+2] != ' '))
        return 0;

    i += 3;
    
    int offset;
    
    if (sscanf(line + i, "%d, ", &offset) != 1)
        return 0;

    while (line[i] && line[i] != ' ')
        ++i;

    ++i;
    
    int matchResult;
    
    if (sscanf(line + i, "%d, ", &matchResult) != 1)
        return 0;
    
    while (line[i] && line[i] != ' ')
        ++i;
    
    ++i;
    
    if (line[i++] != '(')
        return 0;

    int start, end;
    
    RegExpTest* result = new RegExpTest();
    
    result->subject = subjectString.toUString();
    result->offset = offset;
    result->result = matchResult;

    while (line[i] && line[i] != ')') {
        if (sscanf(line + i, "%d, %d", &start, &end) != 2) {
            delete result;
            return 0;
        }

        result->expectVector.append(start);
        result->expectVector.append(end);

        while (line[i] && (line[i] != ',') && (line[i] != ')'))
            i++;
        i++;
        while (line[i] && (line[i] != ',') && (line[i] != ')'))
            i++;

        if (line[i] == ')')
            break;
        if (!line[i] || (line[i] != ',')) {
            delete result;
            return 0;
        }
        i++;
    }

    return result;
}
static int scanString(char* buffer, int bufferLength, UStringBuilder& builder, char termChar)
{
    bool escape = false;
    
    for (int i = 0; i < bufferLength; ++i) {
        UChar c = buffer[i];
        
        if (escape) {
            switch (c) {
            case '0':
                c = '\0';
                break;
            case 'a':
                c = '\a';
                break;
            case 'b':
                c = '\b';
                break;
            case 'f':
                c = '\f';
                break;
            case 'n':
                c = '\n';
                break;
            case 'r':
                c = '\r';
                break;
            case 't':
                c = '\t';
                break;
            case 'v':
                c = '\v';
                break;
            case '\\':
                c = '\\';
                break;
            case '?':
                c = '\?';
                break;
            case 'u':
                if ((i + 4) >= bufferLength)
                    return -1;
                unsigned int charValue;
                if (sscanf(buffer+i+1, "%04x", &charValue) != 1)
                    return -1;
                c = static_cast<UChar>(charValue);
                i += 4;
                break;
            }
            
            builder.append(c);
            escape = false;
        } else {
            if (c == termChar)
                return i;

            if (c == '\\')
                escape = true;
            else
                builder.append(c);
        }
    }

    return -1;
}
// "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions.
template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
{
    ++m_ptr;
    const UChar* runStart;
    UStringBuilder builder;
    do {
        runStart = m_ptr;
        while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr))
            ++m_ptr;
        if (runStart < m_ptr)
            builder.append(runStart, m_ptr - runStart);
        if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
            ++m_ptr;
            if (m_ptr >= m_end)
                return TokError;
            switch (*m_ptr) {
                case '"':
                    builder.append('"');
                    m_ptr++;
                    break;
                case '\\':
                    builder.append('\\');
                    m_ptr++;
                    break;
                case '/':
                    builder.append('/');
                    m_ptr++;
                    break;
                case 'b':
                    builder.append('\b');
                    m_ptr++;
                    break;
                case 'f':
                    builder.append('\f');
                    m_ptr++;
                    break;
                case 'n':
                    builder.append('\n');
                    m_ptr++;
                    break;
                case 'r':
                    builder.append('\r');
                    m_ptr++;
                    break;
                case 't':
                    builder.append('\t');
                    m_ptr++;
                    break;

                case 'u':
                    if ((m_end - m_ptr) < 5) // uNNNN == 5 characters
                        return TokError;
                    for (int i = 1; i < 5; i++) {
                        if (!isASCIIHexDigit(m_ptr[i]))
                            return TokError;
                    }
                    builder.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
                    m_ptr += 5;
                    break;

                default:
                    return TokError;
            }
        }
    } while ((mode == StrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != '"');

    if (m_ptr >= m_end || *m_ptr != '"')
        return TokError;

    token.stringToken = builder.toUString();
    token.type = TokString;
    token.end = ++m_ptr;
    return TokString;
}
示例#9
0
JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
{
    UString pattern = asRegExpObject(slotBase)->regExp()->pattern();
    unsigned length = pattern.length();
    const UChar* characters = pattern.characters();
    bool previousCharacterWasBackslash = false;
    bool inBrackets = false;
    bool shouldEscape = false;

    // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/',
    // and also states that the result must be a valid RegularExpressionLiteral. '//' is
    // not a valid RegularExpressionLiteral (since it is a single line comment), and hence
    // source cannot ever validly be "". If the source is empty, return a different Pattern
    // that would match the same thing.
    if (!length)
        return jsString(exec, "(?:)");

    // early return for strings that don't contain a forwards slash and LineTerminator
    for (unsigned i = 0; i < length; ++i) {
        UChar ch = characters[i];
        if (!previousCharacterWasBackslash) {
            if (inBrackets) {
                if (ch == ']')
                    inBrackets = false;
            } else {
                if (ch == '/') {
                    shouldEscape = true;
                    break;
                }
                if (ch == '[')
                    inBrackets = true;
            }
        }

        if (Lexer<UChar>::isLineTerminator(ch)) {
            shouldEscape = true;
            break;
        }

        if (previousCharacterWasBackslash)
            previousCharacterWasBackslash = false;
        else
            previousCharacterWasBackslash = ch == '\\';
    }

    if (!shouldEscape)
        return jsString(exec, pattern);

    previousCharacterWasBackslash = false;
    inBrackets = false;
    UStringBuilder result;
    for (unsigned i = 0; i < length; ++i) {
        UChar ch = characters[i];
        if (!previousCharacterWasBackslash) {
            if (inBrackets) {
                if (ch == ']')
                    inBrackets = false;
            } else {
                if (ch == '/')
                    result.append('\\');
                else if (ch == '[')
                    inBrackets = true;
            }
        }

        // escape LineTerminator
        if (Lexer<UChar>::isLineTerminator(ch)) {
            if (!previousCharacterWasBackslash)
                result.append('\\');

            if (ch == '\n')
                result.append('n');
            else if (ch == '\r')
                result.append('r');
            else if (ch == 0x2028)
                result.append("u2028");
            else
                result.append("u2029");
        } else
            result.append(ch);

        if (previousCharacterWasBackslash)
            previousCharacterWasBackslash = false;
        else
            previousCharacterWasBackslash = ch == '\\';
    }

    return jsString(exec, result.toUString());
}
示例#10
0
JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
{
    ExecState* exec = toJS(ctx);
    JSLock lock(exec);

    unsigned count = 0;
    UStringBuilder builder;
    CallFrame* callFrame = exec;
    UString functionName;
    if (exec->callee()) {
        if (asObject(exec->callee())->inherits(&InternalFunction::s_info)) {
            functionName = asInternalFunction(exec->callee())->name(exec);
            builder.append("#0 ");
            builder.append(functionName);
            builder.append("() ");
            count++;
        }
    }
    while (true) {
        ASSERT(callFrame);
        int signedLineNumber;
        intptr_t sourceID;
        UString urlString;
        JSValue function;
        
        UString levelStr = UString::number(count);
        
        exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);

        if (function)
            functionName = asFunction(function)->name(exec);
        else {
            // Caller is unknown, but if frame is empty we should still add the frame, because
            // something called us, and gave us arguments.
            if (count)
                break;
        }
        unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0;
        if (!builder.isEmpty())
            builder.append("\n");
        builder.append("#");
        builder.append(levelStr);
        builder.append(" ");
        builder.append(functionName);
        builder.append("() at ");
        builder.append(urlString);
        builder.append(":");
        builder.append(UString::number(lineNumber));
        if (!function || ++count == maxStackSize)
            break;
        callFrame = callFrame->callerFrame();
    }
    return OpaqueJSString::create(builder.toUString()).leakRef();
}
示例#11
0
void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value)
{
    int length = value.length();

    builder.append('"');

    const UChar* data = value.characters();
    for (int i = 0; i < length; ++i) {
        int start = i;
        while (i < length && (data[i] > 0x1F && data[i] != '"' && data[i] != '\\'))
            ++i;
        builder.append(data + start, i - start);
        if (i >= length)
            break;
        switch (data[i]) {
            case '\t':
                builder.append('\\');
                builder.append('t');
                break;
            case '\r':
                builder.append('\\');
                builder.append('r');
                break;
            case '\n':
                builder.append('\\');
                builder.append('n');
                break;
            case '\f':
                builder.append('\\');
                builder.append('f');
                break;
            case '\b':
                builder.append('\\');
                builder.append('b');
                break;
            case '"':
                builder.append('\\');
                builder.append('"');
                break;
            case '\\':
                builder.append('\\');
                builder.append('\\');
                break;
            default:
                static const char hexDigits[] = "0123456789abcdef";
                UChar ch = data[i];
                UChar hex[] = { '\\', 'u', hexDigits[(ch >> 12) & 0xF], hexDigits[(ch >> 8) & 0xF], hexDigits[(ch >> 4) & 0xF], hexDigits[ch & 0xF] };
                builder.append(hex, WTF_ARRAY_LENGTH(hex));
                break;
        }
    }
示例#12
0
文件: Error.cpp 项目: 13W/phantomjs
JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source)
{
    JSGlobalData* globalData = &exec->globalData();

    addErrorInfo(globalData, error, line, source);

    UStringBuilder stackString;
    JSArray* stackArray = constructEmptyArray(exec);
    CallFrame* frame = exec;

    stackString.append(error->toString(exec));

    bool functionKnown;
    ReturnAddressPtr pc;

    while (!frame->hasHostCallFrameFlag()) {
        CodeBlock* codeBlock = frame->codeBlock();
        JSObject* arrayItem = constructEmptyObject(exec);

        stackString.append("\n    at ");

        JSObject* callee = frame->callee();
        UString functionName;

        if (callee && callee->inherits(&JSFunction::s_info)) {
            functionName = asFunction(callee)->calculatedDisplayName(exec);
            functionKnown = !functionName.isEmpty();
        } else {
            functionKnown = false;
        }

        if (functionKnown) {
            stackString.append(functionName);
            stackString.append(" (");

            arrayItem->putWithAttributes(
                globalData, Identifier(globalData, functionPropertyName),
                jsString(globalData, functionName), ReadOnly | DontDelete
            );
        }

        UString sourceURL = codeBlock->ownerExecutable()->sourceURL();

        arrayItem->putWithAttributes(
            globalData, Identifier(globalData, sourceURLPropertyName),
            jsString(globalData, sourceURL), ReadOnly | DontDelete
        );

        stackString.append(sourceURL);
        stackString.append(":");

        if (frame != exec) {
            line = codeBlock->lineNumberForBytecodeOffset(codeBlock->bytecodeOffset(pc));
        }

        arrayItem->putWithAttributes(
            globalData, Identifier(globalData, linePropertyName),
            jsNumber(line), ReadOnly | DontDelete
        );

        stackString.append(UString::number(line));

        if (functionKnown) {
            stackString.append(")");
        }

        stackArray->push(exec, JSValue(arrayItem));

        pc = frame->returnPC();
        frame = frame->callerFrame();
    }

    error->putWithAttributes(
        globalData, Identifier(globalData, stackPropertyName),
        jsString(globalData, stackString.toUString()), ReadOnly | DontDelete
    );

    error->putWithAttributes(
        globalData, Identifier(globalData, "stackArray"),
        stackArray, ReadOnly | DontDelete
    );

    return error;
}
示例#13
0
static void appendStringToUStringBuilder(UStringBuilder& builder, const CharType* data, int length)
{
    for (int i = 0; i < length; ++i) {
        int start = i;
        while (i < length && (data[i] > 0x1F && data[i] != '"' && data[i] != '\\'))
            ++i;
        builder.append(data + start, i - start);
        if (i >= length)
            break;
        switch (data[i]) {
        case '\t':
            builder.append('\\');
            builder.append('t');
            break;
        case '\r':
            builder.append('\\');
            builder.append('r');
            break;
        case '\n':
            builder.append('\\');
            builder.append('n');
            break;
        case '\f':
            builder.append('\\');
            builder.append('f');
            break;
        case '\b':
            builder.append('\\');
            builder.append('b');
            break;
        case '"':
            builder.append('\\');
            builder.append('"');
            break;
        case '\\':
            builder.append('\\');
            builder.append('\\');
            break;
        default:
            static const char hexDigits[] = "0123456789abcdef";
            UChar ch = data[i];
            LChar hex[] = { '\\', 'u', hexDigits[(ch >> 12) & 0xF], hexDigits[(ch >> 8) & 0xF], hexDigits[(ch >> 4) & 0xF], hexDigits[ch & 0xF] };
            builder.append(hex, WTF_ARRAY_LENGTH(hex));
            break;
        }
    }