JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue* v) { if (v->isUndefinedOrNull()) return new (exec) JSPropertyNameIterator(0, 0, 0); JSObject* o = v->toObject(exec); PropertyNameArray propertyNames(exec); o->getPropertyNames(exec, propertyNames); size_t numProperties = propertyNames.size(); return new (exec) JSPropertyNameIterator(o, propertyNames.releaseIdentifiers(), numProperties); }
JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object) { JSLock lock; JSObject* jsObject = toJS(object); ExecState* exec = toJS(ctx); JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(&exec->globalData()); jsObject->getPropertyNames(exec, propertyNames->array); return JSPropertyNameArrayRetain(propertyNames); }
void ScopeChainNode::print() const { ScopeChainIterator scopeEnd = end(); for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) { JSObject* o = *scopeIter; PropertyNameArray propertyNames(globalObject->globalExec()); o->getPropertyNames(globalObject->globalExec(), propertyNames); PropertyNameArray::const_iterator propEnd = propertyNames.end(); fprintf(stderr, "----- [scope %p] -----\n", o); for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) { Identifier name = *propIter; fprintf(stderr, "%s, ", name.ustring().utf8().data()); } fprintf(stderr, "\n"); } }
JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object) { JSObject* jsObject = toJS(object); ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSGlobalData* globalData = &exec->globalData(); JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(globalData); PropertyNameArray array(globalData); jsObject->getPropertyNames(exec, array); size_t size = array.size(); propertyNames->array.reserveInitialCapacity(size); for (size_t i = 0; i < size; ++i) propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).releaseRef())); return JSPropertyNameArrayRetain(propertyNames); }
void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { getOwnPropertyNames(exec, propertyNames, mode); if (prototype().isNull()) return; JSObject* prototype = asObject(this->prototype()); while(1) { if (prototype->structure()->typeInfo().overridesGetPropertyNames()) { prototype->getPropertyNames(exec, propertyNames, mode); break; } prototype->getOwnPropertyNames(exec, propertyNames, mode); JSValue nextProto = prototype->prototype(); if (nextProto.isNull()) break; prototype = asObject(nextProto); } }
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) { bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary()); if (shouldCache && m_cachedPropertyNameArrayData) { if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) { propertyNames.setData(m_cachedPropertyNameArrayData); return; } clearEnumerationCache(); } baseObject->getOwnPropertyNames(exec, propertyNames); if (m_prototype.isObject()) { propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly. JSObject* prototype = asObject(m_prototype); while(1) { if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) { prototype->getPropertyNames(exec, propertyNames); break; } prototype->getOwnPropertyNames(exec, propertyNames); JSValue nextProto = prototype->prototype(); if (!nextProto.isObject()) break; prototype = asObject(nextProto); } } if (shouldCache) { StructureChain* protoChain = prototypeChain(exec); m_cachedPropertyNameArrayData = propertyNames.data(); if (!protoChain->isCacheable()) return; m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain); m_cachedPropertyNameArrayData->setCachedStructure(this); } }
//-------------------------------------------------------------------------- // KJSValueToCFTypeInternal //-------------------------------------------------------------------------- // Caller is responsible for releasing the returned CFTypeRef CFTypeRef KJSValueToCFTypeInternal(JSValue inValue, ExecState *exec, ObjectImpList* inImps) { if (!inValue) return 0; CFTypeRef result = 0; JSGlueAPIEntry entry; if (inValue.isBoolean()) { result = inValue.toBoolean(exec) ? kCFBooleanTrue : kCFBooleanFalse; RetainCFType(result); return result; } if (inValue.isString()) { UString uString = inValue.toString(exec); result = UStringToCFString(uString); return result; } if (inValue.isNumber()) { double number1 = inValue.toNumber(exec); double number2 = (double)inValue.toInteger(exec); if (number1 == number2) { int intValue = (int)number2; result = CFNumberCreate(0, kCFNumberIntType, &intValue); } else { result = CFNumberCreate(0, kCFNumberDoubleType, &number1); } return result; } if (inValue.isObject()) { if (inValue.inherits(&UserObjectImp::info)) { UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(asObject(inValue)); JSUserObject* ptr = userObjectImp->GetJSUserObject(); if (ptr) { result = ptr->CopyCFValue(); } } else { JSObject *object = inValue.toObject(exec); UInt8 isArray = false; // if two objects reference each JSObject* imp = object; ObjectImpList* temp = inImps; while (temp) { if (imp == temp->imp) { return CFRetain(GetCFNull()); } temp = temp->next; } ObjectImpList imps; imps.next = inImps; imps.imp = imp; //[...] HACK since we do not have access to the class info we use class name instead #if 0 if (object->inherits(&ArrayInstanceImp::info)) #else if (object->className() == "Array") #endif { isArray = true; JSGlueGlobalObject* globalObject = static_cast<JSGlueGlobalObject*>(exec->dynamicGlobalObject()); if (globalObject && (globalObject->Flags() & kJSFlagConvertAssociativeArray)) { PropertyNameArray propNames(exec); object->getPropertyNames(exec, propNames); PropertyNameArray::const_iterator iter = propNames.begin(); PropertyNameArray::const_iterator end = propNames.end(); while(iter != end && isArray) { Identifier propName = *iter; UString ustr = propName.ustring(); const UniChar* uniChars = (const UniChar*)ustr.characters(); int size = ustr.length(); while (size--) { if (uniChars[size] < '0' || uniChars[size] > '9') { isArray = false; break; } } iter++; } } } if (isArray) { // This is an KJS array unsigned int length = object->get(exec, Identifier(exec, "length")).toUInt32(exec); result = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); if (result) { for (unsigned i = 0; i < length; i++) { CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, i), exec, &imps); CFArrayAppendValue((CFMutableArrayRef)result, cfValue); ReleaseCFType(cfValue); } } } else { // Not an array, just treat it like a dictionary which contains (property name, property value) pairs PropertyNameArray propNames(exec); object->getPropertyNames(exec, propNames); { result = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (result) { PropertyNameArray::const_iterator iter = propNames.begin(); PropertyNameArray::const_iterator end = propNames.end(); while(iter != end) { Identifier propName = *iter; if (object->hasProperty(exec, propName)) { CFStringRef cfKey = IdentifierToCFString(propName); CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, propName), exec, &imps); if (cfKey && cfValue) { CFDictionaryAddValue((CFMutableDictionaryRef)result, cfKey, cfValue); } ReleaseCFType(cfKey); ReleaseCFType(cfValue); } iter++; } } } } } return result; } if (inValue.isUndefinedOrNull()) { result = RetainCFType(GetCFNull()); return result; } ASSERT_NOT_REACHED(); return 0; }