bool TiValueIsNull(TiContextRef ctx, TiValueRef value) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue jsValue = toJS(exec, value); return jsValue.isNull(); }
::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; }
void TiObject::getPropertyNames(TiExcState* exec, PropertyNameArray& propertyNames) { getOwnPropertyNames(exec, propertyNames); if (prototype().isNull()) return; TiObject* prototype = asObject(this->prototype()); while(1) { if (prototype->structure()->typeInfo().overridesGetPropertyNames()) { prototype->getPropertyNames(exec, propertyNames); break; } prototype->getOwnPropertyNames(exec, propertyNames); TiValue nextProto = prototype->prototype(); if (nextProto.isNull()) break; prototype = asObject(nextProto); } }
bool TiString::getOwnPropertySlot(TiExcState* exec, const Identifier& propertyName, PropertySlot& slot) { // The semantics here are really getPropertySlot, not getOwnPropertySlot. // This function should only be called by TiValue::get. if (getStringPropertySlot(exec, propertyName, slot)) return true; if (propertyName == exec->propertyNames().underscoreProto) { slot.setValue(exec->lexicalGlobalObject()->stringPrototype()); return true; } slot.setBase(this); TiObject* object; for (TiValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) { object = asObject(prototype); if (object->getOwnPropertySlot(exec, propertyName, slot)) return true; } slot.setUndefined(); return true; }
// 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; }