Value RuntimeObjectImp::get(ExecState *exec, const Identifier &propertyName) const { Value result = Undefined(); instance->begin(); Class *aClass = instance->getClass(); if (aClass) { // See if the instance have a field with the specified name. Field *aField = aClass->fieldNamed(propertyName.ascii(), instance); if (aField) { result = instance->getValueOfField (exec, aField); } else { // Now check if a method with specified name exists, if so return a function object for // that method. MethodList methodList = aClass->methodsNamed(propertyName.ascii(), instance); if (methodList.length() > 0) { result = Object (new RuntimeMethodImp(exec, propertyName, methodList)); } } if (result.type() == UndefinedType) { // Try a fallback object. result = aClass->fallbackObject (exec, instance, propertyName); } } instance->end(); return result; }
MethodList EAClass::methodsNamed(const Identifier& identifier, Instance* instance) const { MethodList methodList; // Check to see if the method has been cached first. Method* method = mMethods.get(identifier.impl()); if (method) { methodList.append(method); return methodList; } // Method hasn't been called before, see if the object supports it. // Rather than doing identifier.ascii().data(), we need to create CString separately otherwise it goes out of scope. CString identStr = identifier.ascii(); const char *ident = identStr.data(); const EAInstance *inst = static_cast<const EAInstance*>(instance); EA::WebKit::IJSBoundObject *obj = inst->getObject(); if (obj->hasMethod(ident)) { // The object says it has this method, cache it so that the string // lookup can be avoided in the future. EAMethod* aMethod = new EAMethod(ident); { JSLock lock(SilenceAssertionsOnly); mMethods.set(identifier.impl(), aMethod); } methodList.append(aMethod); } return methodList; }
Value Navigator::get(ExecState *exec, const Identifier &propertyName) const { #ifdef KJS_VERBOSE kdDebug(6070) << "Navigator::get " << propertyName.ascii() << endl; #endif return lookupGet< NavigatorFunc, Navigator, ObjectImp >(exec, propertyName, &NavigatorTable, this); }
MethodList BalClass::methodsNamed(const Identifier& identifier, Instance* instance) const { MethodList methodList; Method* method = m_methods.get(identifier.ustring().rep()); if (method) { methodList.append(method); return methodList; } const char *ident = identifier.ascii(); const BalInstance* inst = static_cast<const BalInstance*>(instance); BalObject* obj = inst->getObject(); if( obj->hasMethod( ident ) ) { Method* aMethod = new BalMethod(ident); // deleted in the CClass destructor { JSLock lock(false); m_methods.set(identifier.ustring().rep(), aMethod); } methodList.append(aMethod); } return methodList; }
Value MozillaSidebarExtension::get(ExecState *exec, const Identifier &propertyName) const { #ifdef KJS_VERBOSE kdDebug(6070) << "MozillaSidebarExtension::get " << propertyName.ascii() << endl; #endif return lookupGet< MozillaSidebarExtensionFunc, MozillaSidebarExtension, ObjectImp >(exec, propertyName, &MozillaSidebarExtensionTable, this); }
bool RuntimeObjectImp::hasProperty(ExecState *exec, const Identifier &propertyName) const { bool result = false; instance->begin(); Field *aField = instance->getClass()->fieldNamed(propertyName.ascii(), instance); if (aField) { instance->end(); return true; } MethodList methodList = instance->getClass()->methodsNamed(propertyName.ascii(), instance); instance->end(); if (methodList.length() > 0) return true; return result; }
bool RuntimeObjectImp::canPut(ExecState *exec, const Identifier &propertyName) const { bool result = false; instance->begin(); Field *aField = instance->getClass()->fieldNamed(propertyName.ascii(), instance); instance->end(); if (aField) return true; return result; }
void RuntimeObjectImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr) { instance->begin(); // Set the value of the property. Field *aField = instance->getClass()->fieldNamed(propertyName.ascii(), instance); if (aField) { getInternalInstance()->setValueOfField(exec, aField, value); } else { if (getInternalInstance()->supportsSetValueOfUndefinedField()){ getInternalInstance()->setValueOfUndefinedField(exec, propertyName, value); } } instance->end(); }
// We use this to get at signals (so we can return a proper function object, // and not get wrapped in RuntimeMethod). Also, use this for methods, // so we can cache the object and return the same object for the same // identifier. JSValue QtClass::fallbackObject(ExecState* exec, Instance* inst, const Identifier& identifier) { QtInstance* qtinst = static_cast<QtInstance*>(inst); QByteArray name(identifier.ascii()); // First see if we have a cache hit JSObject* val = qtinst->m_methods.value(name); if (val) return val; // Nope, create an entry QByteArray normal = QMetaObject::normalizedSignature(name.constData()); // See if there is an exact match int index = -1; if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) { QMetaMethod m = m_metaObject->method(index); if (m.access() != QMetaMethod::Private) { QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false); qtinst->m_methods.insert(name, val); return val; } } // Nope.. try a basename match int count = m_metaObject->methodCount(); for (index = count - 1; index >= 0; --index) { const QMetaMethod m = m_metaObject->method(index); if (m.access() == QMetaMethod::Private) continue; QByteArray signature = m.signature(); signature.truncate(signature.indexOf('(')); if (normal == signature) { QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false); qtinst->m_methods.insert(name, val); return val; } } return jsUndefined(); }
void PropertyMap::put(const Identifier &name, JSValue *value, int attributes, bool roCheck) { assert(!name.isNull()); assert(value != 0); checkConsistency(); UString::Rep *rep = name._ustring.rep(); #if DEBUG_PROPERTIES printf("adding property %s, attributes = 0x%08x (", name.ascii(), attributes); printAttributes(attributes); printf(")\n"); #endif #if USE_SINGLE_ENTRY if (!_table) { UString::Rep *key = _singleEntry.key; if (key) { if (rep == key && !(roCheck && (_singleEntry.attributes & ReadOnly))) { _singleEntry.value = value; return; } } else { rep->ref(); _singleEntry.key = rep; _singleEntry.value = value; _singleEntry.attributes = static_cast<short>(attributes); checkConsistency(); return; } } #endif if (!_table || _table->keyCount * 2 >= _table->size) expand(); unsigned h = rep->hash(); int sizeMask = _table->sizeMask; Entry *entries = _table->entries; int i = h & sizeMask; int k = 0; bool foundDeletedElement = false; int deletedElementIndex = 0; /* initialize to make the compiler happy */ #if DUMP_STATISTICS ++numProbes; numCollisions += entries[i].key && entries[i].key != rep; #endif while (UString::Rep *key = entries[i].key) { if (rep == key) { if (roCheck && (_table->entries[i].attributes & ReadOnly)) return; // Put a new value in an existing hash table entry. entries[i].value = value; // Attributes are intentionally not updated. return; } // If we find the deleted-element sentinel, remember it for use later. if (key == deletedSentinel() && !foundDeletedElement) { foundDeletedElement = true; deletedElementIndex = i; } if (k == 0) k = 1 | (h % sizeMask); i = (i + k) & sizeMask; #if DUMP_STATISTICS ++numRehashes; #endif } // Use either the deleted element or the 0 at the end of the chain. if (foundDeletedElement) { i = deletedElementIndex; --_table->sentinelCount; } // Create a new hash table entry. rep->ref(); entries[i].key = rep; entries[i].value = value; entries[i].attributes = static_cast<short>(attributes); entries[i].index = ++_table->lastIndexUsed; ++_table->keyCount; checkConsistency(); }
// ECMA 8.6.2.2 void JSObject::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) { assert(value); // non-standard netscape extension if (propertyName == exec->propertyNames().underscoreProto) { JSObject* proto = value->getObject(); while (proto) { if (proto == this) { throwError(exec, GeneralError, "cyclic __proto__ value"); return; } proto = proto->prototype() ? proto->prototype()->getObject() : 0; } setPrototype(value); return; } // putValue() is used for JS assignemnts. It passes no attribute. // Assume that a C++ implementation knows what it is doing // and don't spend time doing a read-only check for it. bool checkRO = (attr == None || attr == DontDelete); if (checkRO) { // Check for static properties that are ReadOnly; the property map will check the dynamic properties. // We don't have to worry about setters being read-only as they can't be added with such an attribute. // We also need to inherit any attributes we have from the entry const HashEntry* entry = findPropertyHashEntry(propertyName); if (entry) { if (entry->attr & ReadOnly) { #ifdef KJS_VERBOSE fprintf( stderr, "WARNING: static property %s is ReadOnly\n", propertyName.ascii() ); #endif return; } attr = entry->attr; } } // Check if there are any setters or getters in the prototype chain JSObject *obj = this; bool hasGettersOrSetters = false; while (true) { if (obj->_prop.hasGetterSetterProperties()) { hasGettersOrSetters = true; break; } if (!obj->_proto->isObject()) break; obj = static_cast<JSObject *>(obj->_proto); } if (hasGettersOrSetters) { obj = this; while (true) { unsigned attributes; if (JSValue *gs = obj->_prop.get(propertyName, attributes)) { if (attributes & GetterSetter) { JSObject *setterFunc = static_cast<GetterSetterImp *>(gs)->getSetter(); if (!setterFunc) { throwSetterError(exec); return; } List args; args.append(value); setterFunc->call(exec, this, args); return; } else { // If there's an existing property on the object or one of its // prototype it should be replaced, so we just break here. break; } } if (!obj->_proto->isObject()) break; obj = static_cast<JSObject *>(obj->_proto); } } _prop.put(propertyName,value,attr,checkRO); }
// ECMA 8.6.2.2 EXPORT void JSObject::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr) { assert(value); // non-standard netscape extension if (propertyName == exec->propertyNames().underscoreProto) { JSObject* proto = value->getObject(); while (proto) { if (proto == this) throwError(exec, GeneralError, "cyclic __proto__ value"); proto = proto->prototype() ? proto->prototype()->getObject() : 0; } setPrototype(value); return; } /* TODO: check for write permissions directly w/o this call */ /* Doesn't look very easy with the PropertyMap API - David */ // putValue() is used for JS assignemnts. It passes no attribute. // Assume that a C++ implementation knows what it is doing // and let it override the canPut() check. if ((attr == None || attr == DontDelete) && !canPut(exec,propertyName)) { #ifdef KJS_VERBOSE fprintf( stderr, "WARNING: canPut %s said NO\n", propertyName.ascii() ); #endif return; } // Check if there are any setters or getters in the prototype chain JSObject *obj = this; bool hasGettersOrSetters = false; while (true) { if (obj->_prop.hasGetterSetterProperties()) { hasGettersOrSetters = true; break; } if (!obj->_proto->isObject()) break; obj = static_cast<JSObject *>(obj->_proto); } if (hasGettersOrSetters) { obj = this; while (true) { unsigned attributes; if (JSValue *gs = obj->_prop.get(propertyName, attributes)) { if (attributes & GetterSetter) { JSObject *setterFunc = static_cast<GetterSetterImp *>(gs)->getSetter(); if (!setterFunc) { throwSetterError(exec); return; } List args; args.append(value); setterFunc->call(exec, this, args); return; } else { // If there's an existing property on the object or one of its // prototype it should be replaced, so we just break here. break; } } if (!obj->_proto->isObject()) break; obj = static_cast<JSObject *>(obj->_proto); } } _prop.put(propertyName,value,attr); }