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;
}
Exemple #2
0
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;
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
0
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();
}
Exemple #9
0
// 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();
}
Exemple #11
0
// 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);
}
Exemple #12
0
// 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);
}