Пример #1
0
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
    Scope scope(this);

    // find the right context to create the binding on
    ScopedObject activation(scope, d()->engine->globalObject);
    ExecutionContext *ctx = this;
    while (ctx) {
        if (ctx->d()->type >= Type_CallContext) {
            CallContext *c = static_cast<CallContext *>(ctx);
            if (!c->d()->activation)
                c->d()->activation = d()->engine->newObject()->getPointer();
            activation = c->d()->activation;
            break;
        }
        ctx = ctx->d()->outer;
    }

    if (activation->hasProperty(name))
        return;
    Property desc(Primitive::undefinedValue());
    PropertyAttributes attrs(Attr_Data);
    attrs.setConfigurable(deletable);
    activation->__defineOwnProperty__(this, name, desc, attrs);
}
Пример #2
0
void ExecutionContext::markObjects(Managed *m, ExecutionEngine *engine)
{
    ExecutionContext *ctx = static_cast<ExecutionContext *>(m);

    if (ctx->d()->outer)
        ctx->d()->outer->mark(engine);

    // ### shouldn't need these 3 lines
    ctx->d()->callData->thisObject.mark(engine);
    for (int arg = 0; arg < ctx->d()->callData->argc; ++arg)
        ctx->d()->callData->args[arg].mark(engine);

    if (ctx->d()->type >= Type_CallContext) {
        QV4::CallContext *c = static_cast<CallContext *>(ctx);
        for (unsigned local = 0, lastLocal = c->d()->function->varCount(); local < lastLocal; ++local)
            c->d()->locals[local].mark(engine);
        if (c->d()->activation)
            c->d()->activation->mark(engine);
        c->d()->function->mark(engine);
    } else if (ctx->d()->type == Type_WithContext) {
        WithContext *w = static_cast<WithContext *>(ctx);
        w->d()->withObject->mark(engine);
    } else if (ctx->d()->type == Type_CatchContext) {
        CatchContext *c = static_cast<CatchContext *>(ctx);
        c->d()->exceptionVarName->mark(engine);
        c->d()->exceptionValue.mark(engine);
    } else if (ctx->d()->type == Type_GlobalContext) {
        GlobalContext *g = static_cast<GlobalContext *>(ctx);
        g->d()->global->mark(engine);
    }
}
Пример #3
0
/*
    member = string name-separator value
*/
bool JsonParser::parseMember(Object *o)
{
    BEGIN << "parseMember";
    Scope scope(context);

    QString key;
    if (!parseString(&key))
        return false;
    QChar token = nextToken();
    if (token != NameSeparator) {
        lastError = QJsonParseError::MissingNameSeparator;
        return false;
    }
    ScopedValue val(scope);
    if (!parseValue(val))
        return false;

    ScopedString s(scope, context->d()->engine->newIdentifier(key));
    uint idx = s->asArrayIndex();
    if (idx < UINT_MAX) {
        o->putIndexed(idx, val);
    } else {
        o->insertMember(s.getPointer(), val);
    }

    END;
    return true;
}
Пример #4
0
bool ExecutionContext::deleteProperty(String *name)
{
    Scope scope(this);
    bool hasWith = false;
    for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
        if (ctx->d()->type == Type_WithContext) {
            hasWith = true;
            WithContext *w = static_cast<WithContext *>(ctx);
            if (w->d()->withObject->hasProperty(name))
                return w->d()->withObject->deleteProperty(name);
        } else if (ctx->d()->type == Type_CatchContext) {
            CatchContext *c = static_cast<CatchContext *>(ctx);
            if (c->d()->exceptionVarName->isEqualTo(name))
                return false;
        } else if (ctx->d()->type >= Type_CallContext) {
            CallContext *c = static_cast<CallContext *>(ctx);
            FunctionObject *f = c->d()->function;
            if (f->needsActivation() || hasWith) {
                uint index = f->function()->internalClass->find(name);
                if (index < UINT_MAX)
                    // ### throw in strict mode?
                    return false;
            }
            if (c->d()->activation && c->d()->activation->hasProperty(name))
                return c->d()->activation->deleteProperty(name);
        } else if (ctx->d()->type == Type_GlobalContext) {
            GlobalContext *g = static_cast<GlobalContext *>(ctx);
            if (g->d()->global->hasProperty(name))
                return g->d()->global->deleteProperty(name);
        }
    }

    if (d()->strictMode)
        throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name->toQString()));
    return true;
}
Пример #5
0
void ExecutionContext::setProperty(String *name, const ValueRef value)
{
    Scope scope(this);
    for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
        if (ctx->d()->type == Type_WithContext) {
            ScopedObject w(scope, static_cast<WithContext *>(ctx)->d()->withObject);
            if (w->hasProperty(name)) {
                w->put(name, value);
                return;
            }
        } else if (ctx->d()->type == Type_CatchContext && static_cast<CatchContext *>(ctx)->d()->exceptionVarName->isEqualTo(name)) {
            static_cast<CatchContext *>(ctx)->d()->exceptionValue = *value;
            return;
        } else {
            ScopedObject activation(scope, (Object *)0);
            if (ctx->d()->type >= Type_CallContext) {
                CallContext *c = static_cast<CallContext *>(ctx);
                if (c->d()->function->function()) {
                    uint index = c->d()->function->function()->internalClass->find(name);
                    if (index < UINT_MAX) {
                        if (index < c->d()->function->formalParameterCount()) {
                            c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1] = *value;
                        } else {
                            index -= c->d()->function->formalParameterCount();
                            c->d()->locals[index] = *value;
                        }
                        return;
                    }
                }
                activation = c->d()->activation;
            } else if (ctx->d()->type == Type_GlobalContext) {
                activation = static_cast<GlobalContext *>(ctx)->d()->global;
            }

            if (activation) {
                if (ctx->d()->type == Type_QmlContext) {
                    activation->put(name, value);
                    return;
                } else {
                    uint member = activation->internalClass()->find(name);
                    if (member < UINT_MAX) {
                        activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
                        return;
                    }
                }
            }
        }
    }
    if (d()->strictMode || name->equals(d()->engine->id_this.getPointer())) {
        ScopedValue n(scope, name->asReturnedValue());
        throwReferenceError(n);
        return;
    }
    d()->engine->globalObject->put(name, value);
}
Пример #6
0
/*
    array = begin-array [ value *( value-separator value ) ] end-array
*/
ReturnedValue JsonParser::parseArray()
{
    Scope scope(context);
    BEGIN << "parseArray";
    Scoped<ArrayObject> array(scope, context->d()->engine->newArrayObject());

    if (++nestingLevel > nestingLimit) {
        lastError = QJsonParseError::DeepNesting;
        return Encode::undefined();
    }

    if (!eatSpace()) {
        lastError = QJsonParseError::UnterminatedArray;
        return Encode::undefined();
    }
    if (*json == EndArray) {
        nextToken();
    } else {
        uint index = 0;
        while (1) {
            ScopedValue val(scope);
            if (!parseValue(val))
                return Encode::undefined();
            array->arraySet(index, val);
            QChar token = nextToken();
            if (token == EndArray)
                break;
            else if (token != ValueSeparator) {
                if (!eatSpace())
                    lastError = QJsonParseError::UnterminatedArray;
                else
                    lastError = QJsonParseError::MissingValueSeparator;
                return Encode::undefined();
            }
            ++index;
        }
    }

    DEBUG << "size =" << array->getLength();
    END;

    --nestingLevel;
    return array.asReturnedValue();
}
Пример #7
0
ReturnedValue JsonParser::parseObject()
{
    if (++nestingLevel > nestingLimit) {
        lastError = QJsonParseError::DeepNesting;
        return Encode::undefined();
    }

    BEGIN << "parseObject pos=" << json;
    Scope scope(context);

    ScopedObject o(scope, context->d()->engine->newObject());

    QChar token = nextToken();
    while (token == Quote) {
        if (!parseMember(o))
            return Encode::undefined();
        token = nextToken();
        if (token != ValueSeparator)
            break;
        token = nextToken();
        if (token == EndObject) {
            lastError = QJsonParseError::MissingObject;
            return Encode::undefined();
        }
    }

    DEBUG << "end token=" << token;
    if (token != EndObject) {
        lastError = QJsonParseError::UnterminatedObject;
        return Encode::undefined();
    }

    END;

    --nestingLevel;
    return o.asReturnedValue();
}
Пример #8
0
QString Stringify::Str(const QString &key, ValueRef v)
{
    Scope scope(ctx);

    ScopedValue value(scope, *v);
    ScopedObject o(scope, value);
    if (o) {
        ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
        Scoped<FunctionObject> toJSON(scope, o->get(s.getPointer()));
        if (!!toJSON) {
            ScopedCallData callData(scope, 1);
            callData->thisObject = value;
            callData->args[0] = ctx->d()->engine->newString(key);
            value = toJSON->call(callData);
        }
    }

    if (replacerFunction) {
        ScopedObject holder(scope, ctx->d()->engine->newObject());
        holder->put(ctx, QString(), value);
        ScopedCallData callData(scope, 2);
        callData->args[0] = ctx->d()->engine->newString(key);
        callData->args[1] = value;
        callData->thisObject = holder;
        value = replacerFunction->call(callData);
    }

    o = value.asReturnedValue();
    if (o) {
        if (NumberObject *n = o->asNumberObject())
            value = n->value();
        else if (StringObject *so = o->asStringObject())
            value = so->d()->value;
        else if (BooleanObject *b =o->asBooleanObject())
            value = b->value();
    }

    if (value->isNull())
        return QStringLiteral("null");
    if (value->isBoolean())
        return value->booleanValue() ? QStringLiteral("true") : QStringLiteral("false");
    if (value->isString())
        return quote(value->stringValue()->toQString());

    if (value->isNumber()) {
        double d = value->toNumber();
        return std::isfinite(d) ? value->toString(ctx)->toQString() : QStringLiteral("null");
    }

    o = value.asReturnedValue();
    if (o) {
        if (!o->asFunctionObject()) {
            if (o->asArrayObject()) {
                ScopedArrayObject a(scope, o);
                return JA(a);
            } else {
                return JO(o);
            }
        }
    }

    return QString();
}
Пример #9
0
bool JsonParser::parseValue(ValueRef val)
{
    BEGIN << "parse Value" << *json;

    switch ((json++)->unicode()) {
    case 'n':
        if (end - json < 3) {
            lastError = QJsonParseError::IllegalValue;
            return false;
        }
        if (*json++ == 'u' &&
            *json++ == 'l' &&
            *json++ == 'l') {
            *val = Primitive::nullValue();
            DEBUG << "value: null";
            END;
            return true;
        }
        lastError = QJsonParseError::IllegalValue;
        return false;
    case 't':
        if (end - json < 3) {
            lastError = QJsonParseError::IllegalValue;
            return false;
        }
        if (*json++ == 'r' &&
            *json++ == 'u' &&
            *json++ == 'e') {
            *val = Primitive::fromBoolean(true);
            DEBUG << "value: true";
            END;
            return true;
        }
        lastError = QJsonParseError::IllegalValue;
        return false;
    case 'f':
        if (end - json < 4) {
            lastError = QJsonParseError::IllegalValue;
            return false;
        }
        if (*json++ == 'a' &&
            *json++ == 'l' &&
            *json++ == 's' &&
            *json++ == 'e') {
            *val = Primitive::fromBoolean(false);
            DEBUG << "value: false";
            END;
            return true;
        }
        lastError = QJsonParseError::IllegalValue;
        return false;
    case Quote: {
        QString value;
        if (!parseString(&value))
            return false;
        DEBUG << "value: string";
        END;
        val = context->d()->engine->newString(value);
        return true;
    }
    case BeginArray: {
        *val = parseArray();
        if (val->isUndefined())
            return false;
        DEBUG << "value: array";
        END;
        return true;
    }
    case BeginObject: {
        *val = parseObject();
        if (val->isUndefined())
            return false;
        DEBUG << "value: object";
        END;
        return true;
    }
    case EndArray:
        lastError = QJsonParseError::MissingObject;
        return false;
    default:
        --json;
        if (!parseNumber(val))
            return false;
        DEBUG << "value: number";
        END;
    }

    return true;
}
Пример #10
0
ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Object *&base)
{
    Scope scope(this);
    ScopedValue v(scope);
    base = (Object *)0;
    name->makeIdentifier();

    if (name->equals(d()->engine->id_this.getPointer()))
        return d()->callData->thisObject.asReturnedValue();

    bool hasWith = false;
    bool hasCatchScope = false;
    for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
        if (ctx->d()->type == Type_WithContext) {
            Object *w = static_cast<WithContext *>(ctx)->d()->withObject;
            hasWith = true;
            bool hasProperty = false;
            v = w->get(name, &hasProperty);
            if (hasProperty) {
                base = w;
                return v.asReturnedValue();
            }
            continue;
        }

        else if (ctx->d()->type == Type_CatchContext) {
            hasCatchScope = true;
            CatchContext *c = static_cast<CatchContext *>(ctx);
            if (c->d()->exceptionVarName->isEqualTo(name))
                return c->d()->exceptionValue.asReturnedValue();
        }

        else if (ctx->d()->type >= Type_CallContext) {
            QV4::CallContext *c = static_cast<CallContext *>(ctx);
            FunctionObject *f = c->d()->function;
            if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
                uint index = f->function()->internalClass->find(name);
                if (index < UINT_MAX) {
                    if (index < c->d()->function->formalParameterCount())
                        return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue();
                    return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue();
                }
            }
            if (c->d()->activation) {
                bool hasProperty = false;
                v = c->d()->activation->get(name, &hasProperty);
                if (hasProperty) {
                    if (ctx->d()->type == Type_QmlContext)
                        base = c->d()->activation;
                    return v.asReturnedValue();
                }
            }
            if (f->function() && f->function()->isNamedExpression()
                && name->equals(f->function()->name()))
                return c->d()->function->asReturnedValue();
        }

        else if (ctx->d()->type == Type_GlobalContext) {
            GlobalContext *g = static_cast<GlobalContext *>(ctx);
            bool hasProperty = false;
            v = g->d()->global->get(name, &hasProperty);
            if (hasProperty)
                return v.asReturnedValue();
        }
    }
    ScopedValue n(scope, name);
    return throwReferenceError(n);
}