bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) { Arguments* thisObject = static_cast<Arguments*>(cell); bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < thisObject->d->numArguments) { if (!thisObject->d->deletedArguments) { thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]); memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments); } if (!thisObject->d->deletedArguments[i]) { thisObject->d->deletedArguments[i] = true; return true; } } if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) { thisObject->d->overrodeLength = true; return true; } if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { if (!thisObject->d->isStrictMode) { thisObject->d->overrodeCallee = true; return true; } thisObject->createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && !thisObject->d->isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return JSObject::deleteProperty(thisObject, exec, propertyName); }
void Arguments::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { Arguments* thisObject = static_cast<Arguments*>(cell); bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { if (i < thisObject->d->numParameters) thisObject->d->registers[thisObject->d->firstParameterIndex + i].set(exec->globalData(), thisObject->d->activation ? static_cast<JSCell*>(thisObject->d->activation.get()) : static_cast<JSCell*>(thisObject), value); else thisObject->d->extraArguments[i - thisObject->d->numParameters].set(exec->globalData(), thisObject, value); return; } if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) { thisObject->d->overrodeLength = true; thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum); return; } if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { if (!thisObject->d->isStrictMode) { thisObject->d->overrodeCallee = true; thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum); return; } thisObject->createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); JSObject::put(thisObject, exec, propertyName, value, slot); }
// Special implementation of [[Put]] - see ECMA 15.4.5.1 void ArrayInstanceImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr) { if(propertyName == lengthPropertyName) { unsigned int newLen = value.toUInt32(exec); if(value.toNumber(exec) != double(newLen)) { Object err = Error::create(exec, RangeError, "Invalid array length."); exec->setException(err); return; } setLength(newLen, exec); return; } bool ok; unsigned index = propertyName.toArrayIndex(&ok); if(ok) { putPropertyByIndex(exec, index, value, attr); return; } ObjectImp::put(exec, propertyName, value, attr); }
bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) { descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].get(), None); } else descriptor.setDescriptor(d->extraArguments[i - d->numParameters].get(), None); return true; } if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { descriptor.setDescriptor(jsNumber(d->numArguments), DontEnum); return true; } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { if (!d->isStrictMode) { descriptor.setDescriptor(d->callee.get(), DontEnum); return true; } createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && d->isStrictMode) createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) { slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); } else slot.setValue(d->extraArguments[i - d->numParameters].jsValue()); return true; } if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { slot.setValue(jsNumber(d->numArguments)); return true; } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { if (!d->isStrictMode) { slot.setValue(d->callee); return true; } createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && d->isStrictMode) createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertySlot(exec, propertyName, slot); }
void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) d->registers[d->firstParameterIndex + i] = JSValue(value); else d->extraArguments[i - d->numParameters] = JSValue(value); return; } if (propertyName == exec->propertyNames().length && !d->overrodeLength) { d->overrodeLength = true; putDirect(exec->globalData(), propertyName, value, DontEnum); return; } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { if (!d->isStrictMode) { d->overrodeCallee = true; putDirect(exec->globalData(), propertyName, value, DontEnum); return; } createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && d->isStrictMode) createStrictModeCallerIfNecessary(exec); JSObject::put(exec, propertyName, value, slot); }
bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(exec, length()), DontDelete | DontEnum); return true; } bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex) { if (i >= m_storage->m_length) return false; if (i < m_vectorLength) { JSValue& value = m_storage->m_vector[i]; if (value) { descriptor.setDescriptor(value, 0); return true; } } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) { if (i >= MIN_SPARSE_ARRAY_INDEX) { SparseArrayValueMap::iterator it = map->find(i); if (it != map->end()) { descriptor.setDescriptor(it->second, 0); return true; } } } } return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool Arguments::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { Arguments* thisObject = static_cast<Arguments*>(cell); bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { if (i < thisObject->d->numParameters) { slot.setValue(thisObject->d->registers[thisObject->d->firstParameterIndex + i].get()); } else slot.setValue(thisObject->d->extraArguments[i - thisObject->d->numParameters].get()); return true; } if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->d->overrodeLength)) { slot.setValue(jsNumber(thisObject->d->numArguments)); return true; } if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->d->overrodeCallee)) { if (!thisObject->d->isStrictMode) { slot.setValue(thisObject->d->callee.get()); return true; } thisObject->createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); }
bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex && i < d->numArguments) { if (!d->deletedArguments) { d->deletedArguments.set(new bool[d->numArguments]); memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments); } if (!d->deletedArguments[i]) { d->deletedArguments[i] = true; return true; } } if (propertyName == exec->propertyNames().length && !d->overrodeLength) { d->overrodeLength = true; return true; } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { d->overrodeCallee = true; return true; } return JSObject::deleteProperty(exec, propertyName); }
void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) d->registers[d->firstParameterIndex + i] = value; else d->extraArguments[i - d->numParameters] = value; return; } if (propertyName == exec->propertyNames().length && !d->overrodeLength) { d->overrodeLength = true; putDirect(propertyName, value, DontEnum); return; } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { d->overrodeCallee = true; putDirect(propertyName, value, DontEnum); return; } JSObject::put(exec, propertyName, value, slot); }
bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex) return deleteProperty(exec, i); if (propertyName == exec->propertyNames().length) return false; return JSObject::deleteProperty(exec, propertyName); }
bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (propertyName == exec->propertyNames().length) { slot.setValue(jsNumber(exec, length())); return true; } bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex) return JSArray::getOwnPropertySlot(exec, i, slot); return JSObject::getOwnPropertySlot(exec, propertyName, slot); }
// Special implementation of [[Put]] - see ECMA 15.4.5.1 void ArrayInstanceImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr) { if (propertyName == lengthPropertyName) { setLength(value.toUInt32(exec), exec); return; } bool ok; unsigned index = propertyName.toArrayIndex(&ok); if (ok) { put(exec, index, value, attr); return; } ObjectImp::put(exec, propertyName, value, attr); }
void RuntimeArray::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot) { if (propertyName == exec->propertyNames().length) { throwError(exec, RangeError); return; } bool ok; unsigned index = propertyName.toArrayIndex(&ok); if (ok) { getConcreteArray()->setValueAt(exec, index, value); return; } JSObject::put(exec, propertyName, value, slot); }
void RuntimeArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { RuntimeArray* thisObject = static_cast<RuntimeArray*>(cell); if (propertyName == exec->propertyNames().length) { throwError(exec, createRangeError(exec, "Range error")); return; } bool ok; unsigned index = propertyName.toArrayIndex(ok); if (ok) { thisObject->getConcreteArray()->setValueAt(exec, index, value); return; } JSObject::put(thisObject, exec, propertyName, value, slot); }
bool RuntimeArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (propertyName == exec->propertyNames().length) { slot.setCustom(this, lengthGetter); return true; } bool ok; unsigned index = propertyName.toArrayIndex(&ok); if (ok) { if (index < getLength()) { slot.setCustomIndex(this, index, indexGetter); return true; } } return JSObject::getOwnPropertySlot(exec, propertyName, slot); }
bool ArrayInstance::deleteProperty(ExecState* exec, const Identifier &propertyName) { if (propertyName == exec->propertyNames().length) return false; bool ok; uint32_t index = propertyName.toArrayIndex(&ok); if (ok) { if (index >= length) return true; if (index < storageLength) { storage[index] = 0; return true; } } return JSObject::deleteProperty(exec, propertyName); }
bool ArrayInstanceImp::hasProperty(ExecState *exec, const Identifier &propertyName) const { if (propertyName == lengthPropertyName) return true; bool ok; unsigned index = propertyName.toArrayIndex(&ok); if (ok) { if (index >= length) return false; if (index < storageLength) { ValueImp *v = storage[index]; return v && v != UndefinedImp::staticUndefined; } } return ObjectImp::hasProperty(exec, propertyName); }
Value ArrayInstanceImp::get(ExecState *exec, const Identifier &propertyName) const { if (propertyName == lengthPropertyName) return Number(length); bool ok; unsigned index = propertyName.toArrayIndex(&ok); if (ok) { if (index >= length) return Undefined(); if (index < storageLength) { ValueImp *v = storage[index]; return v ? Value(v) : Undefined(); } } return ObjectImp::get(exec, propertyName); }
Value StringInstanceImp::get(ExecState *exec, const Identifier &propertyName) const { if (propertyName == lengthPropertyName) return Number(internalValue().toString(exec).size()); bool ok; const unsigned index = propertyName.toArrayIndex(&ok); if (ok) { const UString s = internalValue().toString(exec); const unsigned length = s.size(); if (index < length) { const UChar c = s[index]; return String(UString(&c, 1)); } } return ObjectImp::get(exec, propertyName); }
bool RuntimeArray::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { RuntimeArray* thisObject = static_cast<RuntimeArray*>(cell); if (propertyName == exec->propertyNames().length) { slot.setCacheableCustom(thisObject, thisObject->lengthGetter); return true; } bool ok; unsigned index = propertyName.toArrayIndex(ok); if (ok) { if (index < thisObject->getLength()) { slot.setCustomIndex(thisObject, index, thisObject->indexGetter); return true; } } return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); }
bool ArrayInstanceImp::deleteProperty(ExecState *exec, const Identifier &propertyName) { if(propertyName == lengthPropertyName) return false; bool ok; unsigned index = propertyName.toArrayIndex(&ok); if(ok) { if(index >= length) return true; if(index < storageLength) { storage[index] = 0; return true; } } return ObjectImp::deleteProperty(exec, propertyName); }
// ECMA 15.4.5.1 void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex) { put(exec, i, value); return; } if (propertyName == exec->propertyNames().length) { unsigned newLength = value.toUInt32(exec); if (value.toNumber(exec) != static_cast<double>(newLength)) { throwError(exec, RangeError, "Invalid array length."); return; } setLength(newLength); return; } JSObject::put(exec, propertyName, value, slot); }
// Special implementation of [[Put]] - see ECMA 15.4.5.1 void ArrayInstance::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr) { if (propertyName == exec->propertyNames().length) { unsigned int newLen = value->toUInt32(exec); if (value->toNumber(exec) != double(newLen)) { throwError(exec, RangeError, "Invalid array length."); return; } setLength(newLen, exec); return; } bool ok; unsigned index = propertyName.toArrayIndex(&ok); if (ok) { put(exec, index, value, attr); return; } JSObject::put(exec, propertyName, value, attr); }
bool RuntimeArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (propertyName == exec->propertyNames().length) { PropertySlot slot; slot.setCustom(this, lengthGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } bool ok; unsigned index = propertyName.toArrayIndex(ok); if (ok) { if (index < getLength()) { PropertySlot slot; slot.setCustomIndex(this, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | DontEnum); return true; } } return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool ArrayInstance::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (propertyName == exec->propertyNames().length) { slot.setCustom(this, lengthGetter); return true; } bool ok; unsigned index = propertyName.toArrayIndex(&ok); if (ok) { if (index >= length) return false; if (index < storageLength) { JSValue *v = storage[index]; if (!v) return false; slot.setValueSlot(this, &storage[index]); return true; } } return JSObject::getOwnPropertySlot(exec, propertyName, slot); }
void ArrayInstance::setLength(unsigned newLength, ExecState *exec) { if (newLength <= storageLength) { resizeStorage(newLength); } if (newLength < length) { PropertyNameArray sparseProperties; _prop.getSparseArrayPropertyNames(sparseProperties); PropertyNameArrayIterator end = sparseProperties.end(); for (PropertyNameArrayIterator it = sparseProperties.begin(); it != end; ++it) { Identifier name = *it; bool ok; unsigned index = name.toArrayIndex(&ok); if (ok && index > newLength) deleteProperty(exec, name); } } length = newLength; }
bool JSDOMWindowBase::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { // Check for child frames by name before built-in properties to // match Mozilla. This does not match IE, but some sites end up // naming frames things that conflict with window properties that // are in Moz but not IE. Since we have some of these, we have to do // it the Moz way. if (impl()->frame()->tree()->child(propertyName)) { slot.setCustom(this, childFrameGetter); return true; } const HashEntry* entry = JSDOMWindowBaseTable.entry(exec, propertyName); if (entry) { if (entry->attributes() & Function) { if (entry->function() == windowProtoFuncShowModalDialog) { if (!canShowModalDialog(impl()->frame())) return false; } if (allowsAccessFrom(exec)) setUpStaticFunctionSlot(exec, entry, this, propertyName, slot); else slot.setUndefined(); } else slot.setCustom(this, entry->propertyGetter()); return true; } // Do prototype lookup early so that functions and attributes in the prototype can have // precedence over the index and name getters. JSValuePtr proto = prototype(); if (proto->isObject()) { if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) { if (!allowsAccessFrom(exec)) slot.setUndefined(); return true; } } // FIXME: Search the whole frame hierachy somewhere around here. // We need to test the correct priority order. // allow window[1] or parent[1] etc. (#56983) bool ok; unsigned i = propertyName.toArrayIndex(&ok); if (ok && i < impl()->frame()->tree()->childCount()) { slot.setCustomIndex(this, i, indexGetter); return true; } if (!allowsAccessFrom(exec)) { slot.setUndefined(); return true; } // Allow shortcuts like 'Image1' instead of document.images.Image1 Document* document = impl()->frame()->document(); if (document && document->isHTMLDocument()) { AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName); if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { slot.setCustom(this, namedItemGetter); return true; } } return Base::getOwnPropertySlot(exec, propertyName, slot); }
bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { // When accessing a Window cross-domain, functions are always the native built-in ones, and they // are not affected by properties changed on the Window or anything in its prototype chain. // This is consistent with the behavior of Firefox. const HashEntry* entry; // We don't want any properties other than "close" and "closed" on a closed window. if (!impl()->frame()) { // The following code is safe for cross-domain and same domain use. // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype). entry = s_info.propHashTable(exec)->entry(exec, propertyName); if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) { slot.setCustom(this, entry->propertyGetter()); return true; } entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) { slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); return true; } // FIXME: We should have a message here that explains why the property access/function call was // not allowed. slot.setUndefined(); return true; } // We need to check for cross-domain access here without printing the generic warning message // because we always allow access to some function, just different ones depending whether access // is allowed. String errorMessage; bool allowsAccess = allowsAccessFrom(exec, errorMessage); // Look for overrides before looking at any of our own properties, but ignore overrides completely // if this is cross-domain access. if (allowsAccess && JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot)) return true; // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot. // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of // what prototype is actually set on this object. entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry) { if (entry->attributes() & Function) { if (entry->function() == jsDOMWindowPrototypeFunctionBlur) { if (!allowsAccess) { slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>); return true; } } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) { if (!allowsAccess) { slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); return true; } } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) { if (!allowsAccess) { slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>); return true; } } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) { if (!allowsAccess) { slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>); return true; } } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) { if (!DOMWindow::canShowModalDialog(impl()->frame())) { slot.setUndefined(); return true; } } } } else { // Allow access to toString() cross-domain, but always Object.prototype.toString. if (propertyName == exec->propertyNames().toString) { if (!allowsAccess) { slot.setCustom(this, objectToStringFunctionGetter); return true; } } } entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry) { slot.setCustom(this, entry->propertyGetter()); return true; } // Check for child frames by name before built-in properties to // match Mozilla. This does not match IE, but some sites end up // naming frames things that conflict with window properties that // are in Moz but not IE. Since we have some of these, we have to do // it the Moz way. if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) { slot.setCustom(this, childFrameGetter); return true; } // Do prototype lookup early so that functions and attributes in the prototype can have // precedence over the index and name getters. JSValue proto = prototype(); if (proto.isObject()) { if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) { if (!allowsAccess) { printErrorMessage(errorMessage); slot.setUndefined(); } return true; } } // FIXME: Search the whole frame hierarchy somewhere around here. // We need to test the correct priority order. // allow window[1] or parent[1] etc. (#56983) bool ok; unsigned i = propertyName.toArrayIndex(ok); if (ok && i < impl()->frame()->tree()->childCount()) { slot.setCustomIndex(this, i, indexGetter); return true; } if (!allowsAccess) { printErrorMessage(errorMessage); slot.setUndefined(); return true; } // Allow shortcuts like 'Image1' instead of document.images.Image1 Document* document = impl()->frame()->document(); if (document->isHTMLDocument()) { AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { slot.setCustom(this, namedItemGetter); return true; } } return Base::getOwnPropertySlot(exec, propertyName, slot); }
bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { // Never allow cross-domain getOwnPropertyDescriptor if (!allowsAccessFrom(exec)) return false; const HashEntry* entry; // We don't want any properties other than "close" and "closed" on a closed window. if (!impl()->frame()) { // The following code is safe for cross-domain and same domain use. // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype). entry = s_info.propHashTable(exec)->entry(exec, propertyName); if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) { descriptor.setDescriptor(jsBoolean(true), ReadOnly | DontDelete | DontEnum); return true; } entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) { PropertySlot slot; slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } descriptor.setUndefined(); return true; } entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry) { PropertySlot slot; slot.setCustom(this, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } // Check for child frames by name before built-in properties to // match Mozilla. This does not match IE, but some sites end up // naming frames things that conflict with window properties that // are in Moz but not IE. Since we have some of these, we have to do // it the Moz way. if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) { PropertySlot slot; slot.setCustom(this, childFrameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } bool ok; unsigned i = propertyName.toArrayIndex(ok); if (ok && i < impl()->frame()->tree()->childCount()) { PropertySlot slot; slot.setCustomIndex(this, i, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } // Allow shortcuts like 'Image1' instead of document.images.Image1 Document* document = impl()->frame()->document(); if (document->isHTMLDocument()) { AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { PropertySlot slot; slot.setCustom(this, namedItemGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } } return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); }