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)); }
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); }
bool TiValueIsObject(TiContextRef ctx, TiValueRef value) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue jsValue = toJS(exec, value); return jsValue.isObject(); }
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; }
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); } }
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(); } }
::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; }
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; }
// 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; }