EncodedTiValue JSC_HOST_CALL functionProtoFuncApply(TiExcState* exec)
{
    TiValue thisValue = exec->hostThisValue();
    CallData callData;
    CallType callType = getCallData(thisValue, callData);
    if (callType == CallTypeNone)
        return throwVMTypeError(exec);

    TiValue array = exec->argument(1);

    MarkedArgumentBuffer applyArgs;
    if (!array.isUndefinedOrNull()) {
        if (!array.isObject())
            return throwVMTypeError(exec);
        if (asObject(array)->classInfo() == &Arguments::s_info)
            asArguments(array)->fillArgList(exec, applyArgs);
        else if (isTiArray(&exec->globalData(), array))
            asArray(array)->fillArgList(exec, applyArgs);
        else if (asObject(array)->inherits(&TiArray::s_info)) {
            unsigned length = asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
            for (unsigned i = 0; i < length; ++i)
                applyArgs.append(asArray(array)->get(exec, i));
        } else
            return throwVMTypeError(exec);
    }

    return TiValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), applyArgs));
}
Exemple #2
0
TiObject* TiFunction::construct(TiExcState* exec, const ArgList& args)
{
    ASSERT(!isHostFunction());
    Structure* structure;
    TiValue prototype = get(exec, exec->propertyNames().prototype);
    if (prototype.isObject())
        structure = asObject(prototype)->inheritorID();
    else
        structure = exec->lexicalGlobalObject()->emptyObjectStructure();
    TiObject* thisObj = new (exec) TiObject(structure);

    TiValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
    if (exec->hadException() || !result.isObject())
        return thisObj;
    return asObject(result);
}
Exemple #3
0
bool TiValueIsObject(TiContextRef ctx, TiValueRef value)
{
    TiExcState* exec = toJS(ctx);
    APIEntryShim entryShim(exec);

    TiValue jsValue = toJS(exec, value);
    return jsValue.isObject();
}
Exemple #4
0
bool TiObject::hasInstance(TiExcState* exec, TiValue value, TiValue proto)
{
    if (!value.isObject())
        return false;

    if (!proto.isObject()) {
        throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
        return false;
    }

    TiObject* object = asObject(value);
    while ((object = object->prototype().getObject())) {
        if (proto == object)
            return true;
    }
    return false;
}
Exemple #5
0
bool TiObject::getPropertyDescriptor(TiExcState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
    TiObject* object = this;
    while (true) {
        if (object->getOwnPropertyDescriptor(exec, propertyName, descriptor))
            return true;
        TiValue prototype = object->prototype();
        if (!prototype.isObject())
            return false;
        object = asObject(prototype);
    }
}
Exemple #6
0
CallIdentifier Profiler::createCallIdentifier(TiExcState* exec, TiValue functionValue, const UString& defaultSourceURL, int defaultLineNumber)
{
    if (!functionValue)
        return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
    if (!functionValue.isObject())
        return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
    if (asObject(functionValue)->inherits(&TiFunction::info)) {
        TiFunction* function = asFunction(functionValue);
        if (!function->executable()->isHostFunction())
            return createCallIdentifierFromFunctionImp(exec, function);
    }
    if (asObject(functionValue)->inherits(&InternalFunction::info))
        return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
    return CallIdentifier(makeString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber);
}
TiValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(TiExcState* exec, TiObject*, TiValue thisValue, const ArgList& args)
{
    TiObject* thisObj = thisValue.toThisObject(exec);

    if (!args.at(0).isObject())
        return jsBoolean(false);

    TiValue v = asObject(args.at(0))->prototype();

    while (true) {
        if (!v.isObject())
            return jsBoolean(false);
        if (v == thisObj)
            return jsBoolean(true);
        v = asObject(v)->prototype();
    }
}
Exemple #8
0
::TiType TiValueGetType(TiContextRef ctx, TiValueRef value)
{
    TiExcState* exec = toJS(ctx);
    APIEntryShim entryShim(exec);

    TiValue jsValue = toJS(exec, value);

    if (jsValue.isUndefined())
        return kTITypeUndefined;
    if (jsValue.isNull())
        return kTITypeNull;
    if (jsValue.isBoolean())
        return kTITypeBoolean;
    if (jsValue.isNumber())
        return kTITypeNumber;
    if (jsValue.isString())
        return kTITypeString;
    ASSERT(jsValue.isObject());
    return kTITypeObject;
}
Exemple #9
0
static ALWAYS_INLINE TiValue callDefaultValueFunction(TiExcState* exec, const TiObject* object, const Identifier& propertyName)
{
    TiValue function = object->get(exec, propertyName);
    CallData callData;
    CallType callType = function.getCallData(callData);
    if (callType == CallTypeNone)
        return exec->exception();

    // Prevent "toString" and "valueOf" from observing execution if an exception
    // is pending.
    if (exec->hadException())
        return exec->exception();

    TiValue result = call(exec, function, callType, callData, const_cast<TiObject*>(object), exec->emptyList());
    ASSERT(!result.isGetterSetter());
    if (exec->hadException())
        return exec->exception();
    if (result.isObject())
        return TiValue();
    return result;
}
Exemple #10
0
// ECMA 8.6.2.2
void TiObject::put(TiExcState* exec, const Identifier& propertyName, TiValue value, PutPropertySlot& slot)
{
    ASSERT(value);
    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));

    if (propertyName == exec->propertyNames().underscoreProto) {
        // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
        if (!value.isObject() && !value.isNull())
            return;

        TiValue nextPrototypeValue = value;
        while (nextPrototypeValue && nextPrototypeValue.isObject()) {
            TiObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject();
            if (nextPrototype == this) {
                throwError(exec, GeneralError, "cyclic __proto__ value");
                return;
            }
            nextPrototypeValue = nextPrototype->prototype();
        }

        setPrototype(value);
        return;
    }

    // Check if there are any setters or getters in the prototype chain
    TiValue prototype;
    for (TiObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
        prototype = obj->prototype();
        if (prototype.isNull()) {
            putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
            return;
        }
    }
    
    unsigned attributes;
    TiCell* specificValue;
    if ((m_structure->get(propertyName, attributes, specificValue) != WTI::notFound) && attributes & ReadOnly)
        return;

    for (TiObject* obj = this; ; obj = asObject(prototype)) {
        if (TiValue gs = obj->getDirect(propertyName)) {
            if (gs.isGetterSetter()) {
                TiObject* setterFunc = asGetterSetter(gs)->setter();        
                if (!setterFunc) {
                    throwSetterError(exec);
                    return;
                }
                
                CallData callData;
                CallType callType = setterFunc->getCallData(callData);
                MarkedArgumentBuffer args;
                args.append(value);
                call(exec, setterFunc, callType, callData, this, args);
                return;
            }

            // If there's an existing property on the object or one of its 
            // prototypes it should be replaced, so break here.
            break;
        }

        prototype = obj->prototype();
        if (prototype.isNull())
            break;
    }

    putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
    return;
}