bool JSNPObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSNPObject* thisObject = jsCast<JSNPObject*>(object); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); if (!thisObject->m_npObject) { throwInvalidAccessError(exec); return false; } NPIdentifier npIdentifier = npIdentifierFromIdentifier(propertyName); // Calling NPClass::invoke will call into plug-in code, and there's no telling what the plug-in can do. // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until // the call has finished. NPRuntimeObjectMap::PluginProtector protector(thisObject->m_objectMap); // First, check if the NPObject has a property with this name. if (thisObject->m_npObject->_class->hasProperty && thisObject->m_npObject->_class->hasProperty(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, propertyGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } // Second, check if the NPObject has a method with this name. if (thisObject->m_npObject->_class->hasMethod && thisObject->m_npObject->_class->hasMethod(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, methodGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } return false; }
bool JSCSSStyleDeclaration::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { ASSERT_GC_OBJECT_INHERITS(this, &s_info); const HashEntry* entry = JSCSSStyleDeclarationTable.entry(exec, propertyName); if (entry) { PropertySlot slot; slot.setCustom(this, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } bool ok; unsigned index = propertyName.toUInt32(ok); if (ok && index < static_cast<CSSStyleDeclaration*>(impl())->length()) { PropertySlot slot; slot.setCustomIndex(this, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } if (canGetItemsForName(exec, static_cast<CSSStyleDeclaration*>(impl()), propertyName)) { PropertySlot slot; slot.setCustom(this, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSCSSStyleDeclaration, Base>(exec, &JSCSSStyleDeclarationTable, this, propertyName, descriptor); }
bool JSNPObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (!m_npObject) { throwInvalidAccessError(exec); return false; } NPIdentifier npIdentifier = npIdentifierFromIdentifier(propertyName); // First, check if the NPObject has a property with this name. if (m_npObject->_class->hasProperty && m_npObject->_class->hasProperty(m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(this, propertyGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } // Second, check if the NPObject has a method with this name. if (m_npObject->_class->hasMethod && m_npObject->_class->hasMethod(m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(this, methodGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } return false; }
bool JSTestEventTarget::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSTestEventTarget* thisObject = jsCast<JSTestEventTarget*>(object); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); const HashEntry* entry = JSTestEventTargetTable.entry(exec, propertyName); if (entry) { PropertySlot slot; slot.setCustom(thisObject, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } unsigned index = propertyName.asIndex(); if (index != PropertyName::NotAnIndex && index < static_cast<TestEventTarget*>(thisObject->impl())->length()) { PropertySlot slot; slot.setCustomIndex(thisObject, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } if (canGetItemsForName(exec, static_cast<TestEventTarget*>(thisObject->impl()), propertyName)) { PropertySlot slot; slot.setCustom(thisObject, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSTestEventTarget, Base>(exec, &JSTestEventTargetTable, thisObject, propertyName, descriptor); }
bool JSNPObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSNPObject* thisObject = jsCast<JSNPObject*>(object); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); if (!thisObject->m_npObject) { throwInvalidAccessError(exec); return false; } NPIdentifier npIdentifier = npIdentifierFromIdentifier(propertyName); // First, check if the NPObject has a property with this name. if (thisObject->m_npObject->_class->hasProperty && thisObject->m_npObject->_class->hasProperty(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, propertyGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } // Second, check if the NPObject has a method with this name. if (thisObject->m_npObject->_class->hasMethod && thisObject->m_npObject->_class->hasMethod(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, methodGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } return false; }
bool JSNamedNodeMap::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { ASSERT_GC_OBJECT_INHERITS(this, &s_info); JSValue proto = prototype(); if (proto.isObject() && static_cast<JSObject*>(asObject(proto))->hasProperty(exec, propertyName)) return false; const HashEntry* entry = JSNamedNodeMapTable.entry(exec, propertyName); if (entry) { PropertySlot slot; slot.setCustom(this, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } bool ok; unsigned index = propertyName.toUInt32(ok); if (ok && index < static_cast<NamedNodeMap*>(impl())->length()) { PropertySlot slot; slot.setCustomIndex(this, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } if (canGetItemsForName(exec, static_cast<NamedNodeMap*>(impl()), propertyName)) { PropertySlot slot; slot.setCustom(this, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSNamedNodeMap, Base>(exec, &JSNamedNodeMapTable, this, propertyName, descriptor); }
bool RuntimeObject::getOwnPropertyDescriptor(JSObject* object, ExecState *exec, PropertyName propertyName, PropertyDescriptor& descriptor) { RuntimeObject* thisObject = jsCast<RuntimeObject*>(object); if (!thisObject->m_instance) { throwInvalidAccessError(exec); return false; } RefPtr<Instance> instance = thisObject->m_instance; instance->begin(); Class *aClass = instance->getClass(); if (aClass) { // See if the instance has a field with the specified name. Field *aField = aClass->fieldNamed(propertyName, instance.get()); if (aField) { PropertySlot slot; slot.setCustom(thisObject, fieldGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } else { // Now check if a method with specified name exists, if so return a function object for // that method. MethodList methodList = aClass->methodsNamed(propertyName, instance.get()); if (methodList.size() > 0) { PropertySlot slot; slot.setCustom(thisObject, methodGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } } // Try a fallback object. if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) { PropertySlot slot; slot.setCustom(thisObject, fallbackObjectGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); return true; } } instance->end(); return instance->getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { DebuggerScope* scope = jsCast<DebuggerScope*>(object); ASSERT(scope->isValid()); if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); slot.setThisValue(JSValue(thisObject)); // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype // chain and not the wrapped scope, and JSObject::getPropertySlot() cannot be overridden // to behave differently for the DebuggerScope. // // Instead, we'll treat all properties in the wrapped scope and its prototype chain as // the own properties of the DebuggerScope. This is fine because the WebInspector // does not presently need to distinguish between what's owned at each level in the // prototype chain. Hence, we'll invoke getPropertySlot() on the wrapped scope here // instead of getOwnPropertySlot(). bool result = thisObject->getPropertySlot(exec, propertyName, slot); if (result && slot.isValue() && slot.getValue(exec, propertyName) == jsTDZValue()) { // FIXME: // We hit a scope property that has the TDZ empty value. // Currently, we just lie to the inspector and claim that this property is undefined. // This is not ideal and we should fix it. // https://bugs.webkit.org/show_bug.cgi?id=144977 slot.setValue(slot.slotBase(), DontEnum, jsUndefined()); return true; } return result; }
static JSValue *getProperty(ExecState *exec, JSObject *obj, unsigned index) { PropertySlot slot; if (!obj->getPropertySlot(exec, index, slot)) return NULL; return slot.getValue(exec, obj, index); }
JSValue *JSObject::get(ExecState *exec, unsigned propertyName) const { PropertySlot slot; if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, const_cast<JSObject *>(this), propertyName); return jsUndefined(); }
bool JSHistory::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (!impl()->frame()) { descriptor.setUndefined(); return true; } // Throw out all cross domain access if (!allowAccessToFrame(exec, impl()->frame())) return true; // Check for the few functions that we allow, even when called cross-domain. const HashEntry* entry = JSHistoryPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry) { PropertySlot slot; // Allow access to back(), forward() and go() from any frame. if (entry->attributes() & JSC::Function) { if (entry->function() == jsHistoryPrototypeFunctionBack) { slot.setCustom(this, nonCachingStaticBackFunctionGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } else if (entry->function() == jsHistoryPrototypeFunctionForward) { slot.setCustom(this, nonCachingStaticForwardFunctionGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } else if (entry->function() == jsHistoryPrototypeFunctionGo) { slot.setCustom(this, nonCachingStaticGoFunctionGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } } } else { // Allow access to toString() cross-domain, but always Object.toString. if (propertyName == exec->propertyNames().toString) { PropertySlot slot; slot.setCustom(this, objectToStringFunctionGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } } descriptor.setUndefined(); return true; }
bool JSHTMLDocument::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (canGetItemsForName(exec, static_cast<HTMLDocument*>(impl()), propertyName)) { PropertySlot slot; slot.setCustom(this, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSHTMLDocument, Base>(exec, &JSHTMLDocumentTable, this, propertyName, descriptor); }
bool JSEntryArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { const HashEntry* entry = JSEntryArrayTable.entry(exec, propertyName); if (entry) { PropertySlot slot; slot.setCustom(this, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } bool ok; unsigned index = propertyName.toUInt32(ok); if (ok && index < static_cast<EntryArray*>(impl())->length()) { PropertySlot slot; slot.setCustomIndex(this, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } return getStaticValueDescriptor<JSEntryArray, Base>(exec, getJSEntryArrayTable(exec), this, propertyName, descriptor); }
inline JSValue DialogHandler::returnValue() const { JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->globalData())); if (!globalObject) return jsUndefined(); Identifier identifier(m_exec, "returnValue"); PropertySlot slot; if (!JSGlobalObject::getOwnPropertySlot(globalObject, m_exec, identifier, slot)) return jsUndefined(); return slot.getValue(m_exec, identifier); }
bool RuntimeMethod::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; } return InternalFunction::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool RuntimeMethod::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor &descriptor) { RuntimeMethod* thisObject = jsCast<RuntimeMethod*>(object); if (propertyName == exec->propertyNames().length) { PropertySlot slot; slot.setCustom(thisObject, lengthGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return InternalFunction::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
bool JSTestCustomNamedGetter::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSTestCustomNamedGetter* thisObject = jsCast<JSTestCustomNamedGetter*>(object); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); if (canGetItemsForName(exec, static_cast<TestCustomNamedGetter*>(thisObject->impl()), propertyName)) { PropertySlot slot; slot.setCustom(thisObject, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSTestCustomNamedGetter, Base>(exec, &JSTestCustomNamedGetterTable, thisObject, propertyName, descriptor); }
JSValue *JSObject::get(ExecState *exec, const Identifier &propertyName) const { PropertySlot slot; if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot)) { JSValue* val = slot.getValue(exec, const_cast<JSObject *>(this), propertyName); assert(val); return val; } return jsUndefined(); }
bool RuntimeArray::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { RuntimeArray* thisObject = jsCast<RuntimeArray*>(object); if (propertyName == exec->propertyNames().length) { PropertySlot slot; slot.setCustom(thisObject, lengthGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } unsigned index = propertyName.asIndex(); if (index < thisObject->getLength()) { ASSERT(index != PropertyName::NotAnIndex); PropertySlot slot; slot.setCustomIndex(thisObject, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | DontEnum); return true; } return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
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 JSLocation::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { Frame* frame = impl()->frame(); if (!frame) { descriptor.setUndefined(); return true; } // throw out all cross domain access if (!allowAccessToFrame(exec, frame)) return true; // Check for the few functions that we allow, even when called cross-domain. const HashEntry* entry = JSLocationPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); PropertySlot slot; if (entry && (entry->attributes() & JSC::Function)) { if (entry->function() == jsLocationPrototypeFunctionReplace) { slot.setCustom(this, nonCachingStaticReplaceFunctionGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } else if (entry->function() == jsLocationPrototypeFunctionReload) { slot.setCustom(this, nonCachingStaticReloadFunctionGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } else if (entry->function() == jsLocationPrototypeFunctionAssign) { slot.setCustom(this, nonCachingStaticAssignFunctionGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } } // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString, // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in // such cases when normally the string form of Location would be the URL. descriptor.setUndefined(); return true; }
bool runtimeObjectCustomGetOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, JSHTMLElement* element) { RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element->impl()); if (!runtimeObject) return false; if (!runtimeObject->hasProperty(exec, propertyName)) return false; PropertySlot slot; slot.setCustom(element, runtimeObjectPropertyGetter); // While we don't know what the plugin allows, we do know that we prevent // enumeration or deletion of properties, so we mark plugin properties // as DontEnum | DontDelete descriptor.setDescriptor(slot.getValue(exec, propertyName), DontEnum | DontDelete); return true; }
JSValue* JSValue::getByIndex(ExecState* exec, unsigned propertyName) const { switch (type()) { case StringType: { UString s = static_cast<const StringImp*>(asCell())->value(); if (propertyName < static_cast<unsigned>(s.size())) { return jsString(s.substr(propertyName, 1)); } // fall through } default: { JSObject* obj = toObject(exec); PropertySlot slot; if (obj->getPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, obj, propertyName); return jsUndefined(); } } }
// Property access sequence is: // (1) indexed properties, // (2) regular own properties, // (3) named properties (in fact, these shouldn't be on the window, should be on the NPO). bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot) { // (1) First, indexed properties. // Hand off all indexed access to getOwnPropertySlotByIndex, which supports the indexed getter. if (Optional<unsigned> index = parseIndex(propertyName)) return getOwnPropertySlotByIndex(object, state, index.value(), slot); auto* thisObject = jsCast<JSDOMWindow*>(object); auto* frame = thisObject->wrapped().frame(); // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess. String errorMessage; if (!frame || !BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage)) return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, propertyName, slot, errorMessage); // FIXME: this need more explanation. // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?) slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints); // (2) Regular own properties. PropertySlot slotCopy = slot; if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot)) { // Detect when we're getting the property 'showModalDialog', this is disabled, and has its original value. bool isShowModalDialogAndShouldHide = propertyName == state->propertyNames().showModalDialog && !DOMWindow::canShowModalDialog(frame) && slot.isValue() && isHostFunction(slot.getValue(state, propertyName), jsDOMWindowInstanceFunctionShowModalDialog); // Unless we're in the showModalDialog special case, we're done. if (!isShowModalDialogAndShouldHide) return true; slot = slotCopy; } #if ENABLE(USER_MESSAGE_HANDLERS) if (propertyName == state->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) { slot.setCacheableCustom(thisObject, DontDelete | ReadOnly, jsDOMWindowWebKit); return true; } #endif return false; }
JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSActivation* activation = asActivation(slot.slotBase()); if (activation->d()->functionExecutable->usesArguments()) { PropertySlot slot; activation->symbolTableGet(exec->propertyNames().arguments, slot); return slot.getValue(exec, exec->propertyNames().arguments); } CallFrame* callFrame = CallFrame::create(activation->d()->registers); Arguments* arguments = callFrame->optionalCalleeArguments(); if (!arguments) { arguments = new (callFrame) Arguments(callFrame); arguments->copyRegisters(); callFrame->setCalleeArguments(arguments); } ASSERT(arguments->inherits(&Arguments::info)); return arguments; }
JSValue JSDOMWindow::showModalDialog(ExecState* exec) { String url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)); JSValue dialogArgs = exec->argument(1); String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); Frame* frame = impl()->frame(); if (!frame) return jsUndefined(); Frame* lexicalFrame = toLexicalFrame(exec); if (!lexicalFrame) return jsUndefined(); Frame* dynamicFrame = toDynamicFrame(exec); if (!dynamicFrame) return jsUndefined(); if (!DOMWindow::canShowModalDialogNow(frame) || !domWindowAllowPopUp(dynamicFrame)) return jsUndefined(); HashMap<String, String> features; DOMWindow::parseModalDialogFeatures(featureArgs, features); const bool trusted = false; // The following features from Microsoft's documentation are not implemented: // - default font settings // - width, height, left, and top specified in units other than "px" // - edge (sunken or raised, default is raised) // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?) // - unadorned: trusted && boolFeature(features, "unadorned"); FloatRect screenRect = screenAvailableRect(frame->view()); WindowFeatures wargs; wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE wargs.widthSet = true; wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE wargs.heightSet = true; wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1); wargs.xSet = wargs.x > 0; wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1); wargs.ySet = wargs.y > 0; if (WindowFeatures::boolFeature(features, "center", true)) { if (!wargs.xSet) { wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2; wargs.xSet = true; } if (!wargs.ySet) { wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2; wargs.ySet = true; } } wargs.dialog = true; wargs.resizable = WindowFeatures::boolFeature(features, "resizable"); wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true); wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted); wargs.menuBarVisible = false; wargs.toolBarVisible = false; wargs.locationBarVisible = false; wargs.fullscreen = false; Frame* dialogFrame = createWindow(exec, lexicalFrame, dynamicFrame, frame, url, "", wargs, dialogArgs); if (!dialogFrame) return jsUndefined(); JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame, currentWorld(exec)); dialogFrame->page()->chrome()->runModal(); Identifier returnValue(exec, "returnValue"); if (dialogWindow->allowsAccessFromNoErrorMessage(exec)) { PropertySlot slot; // This is safe, we have already performed the origin security check and we are // not interested in any of the DOM properties of the window. if (dialogWindow->JSGlobalObject::getOwnPropertySlot(exec, returnValue, slot)) return slot.getValue(exec, returnValue); } return jsUndefined(); }
// ECMA 15.4.4 JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) { unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); JSValue *result = 0; // work around gcc 4.0 bug in uninitialized variable warning switch (id) { case ToLocaleString: case ToString: if (!thisObj->inherits(&ArrayInstance::info)) return throwError(exec, TypeError); // fall through case Join: { static HashSet<JSObject*> visitedElems; if (visitedElems.contains(thisObj)) return jsString(""); UString separator = ","; UString str = ""; visitedElems.add(thisObj); if (id == Join && !args[0]->isUndefined()) separator = args[0]->toString(exec); for (unsigned int k = 0; k < length; k++) { if (k >= 1) str += separator; if (str.isNull()) { JSObject *error = Error::create(exec, GeneralError, "Out of memory"); exec->setException(error); break; } JSValue* element = thisObj->get(exec, k); if (element->isUndefinedOrNull()) continue; bool fallback = false; if (id == ToLocaleString) { JSObject* o = element->toObject(exec); JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); if (conversionFunction->isObject() && static_cast<JSObject*>(conversionFunction)->implementsCall()) str += static_cast<JSObject*>(conversionFunction)->call(exec, o, List())->toString(exec); else // try toString() fallback fallback = true; } if (id == ToString || id == Join || fallback) str += element->toString(exec); if (str.isNull()) { JSObject *error = Error::create(exec, GeneralError, "Out of memory"); exec->setException(error); } if (exec->hadException()) break; } visitedElems.remove(thisObj); result = jsString(str); break; } case Concat: { JSObject *arr = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty())); int n = 0; JSValue *curArg = thisObj; JSObject *curObj = static_cast<JSObject *>(thisObj); ListIterator it = args.begin(); for (;;) { if (curArg->isObject() && curObj->inherits(&ArrayInstance::info)) { unsigned int k = 0; // Older versions tried to optimize out getting the length of thisObj // by checking for n != 0, but that doesn't work if thisObj is an empty array. length = curObj->get(exec, exec->propertyNames().length)->toUInt32(exec); while (k < length) { if (JSValue *v = getProperty(exec, curObj, k)) arr->put(exec, n, v); n++; k++; } } else { arr->put(exec, n, curArg); n++; } if (it == args.end()) break; curArg = *it; curObj = static_cast<JSObject *>(it++); // may be 0 } arr->put(exec, exec->propertyNames().length, jsNumber(n), DontEnum | DontDelete); result = arr; break; } case Pop:{ if (length == 0) { thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); result = jsUndefined(); } else { result = thisObj->get(exec, length - 1); thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete); } break; } case Push: { for (int n = 0; n < args.size(); n++) thisObj->put(exec, length + n, args[n]); length += args.size(); thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); result = jsNumber(length); break; } case Reverse: { unsigned int middle = length / 2; for (unsigned int k = 0; k < middle; k++) { unsigned lk1 = length - k - 1; JSValue *obj2 = getProperty(exec, thisObj, lk1); JSValue *obj = getProperty(exec, thisObj, k); if (obj2) thisObj->put(exec, k, obj2); else thisObj->deleteProperty(exec, k); if (obj) thisObj->put(exec, lk1, obj); else thisObj->deleteProperty(exec, lk1); } result = thisObj; break; } case Shift: { if (length == 0) { thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); result = jsUndefined(); } else { result = thisObj->get(exec, 0); for(unsigned int k = 1; k < length; k++) { if (JSValue *obj = getProperty(exec, thisObj, k)) thisObj->put(exec, k-1, obj); else thisObj->deleteProperty(exec, k-1); } thisObj->deleteProperty(exec, length - 1); thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete); } break; } case Slice: { // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10 // We return a new array JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty())); result = resObj; double begin = 0; if (!args[0]->isUndefined()) { begin = args[0]->toInteger(exec); if (begin >= 0) { // false for NaN if (begin > length) begin = length; } else { begin += length; if (!(begin >= 0)) // true for NaN begin = 0; } } double end = length; if (!args[1]->isUndefined()) { end = args[1]->toInteger(exec); if (end < 0) { // false for NaN end += length; if (end < 0) end = 0; } else { if (!(end <= length)) // true for NaN end = length; } } //printf( "Slicing from %d to %d \n", begin, end ); int n = 0; int b = static_cast<int>(begin); int e = static_cast<int>(end); for(int k = b; k < e; k++, n++) { if (JSValue *v = getProperty(exec, thisObj, k)) resObj->put(exec, n, v); } resObj->put(exec, exec->propertyNames().length, jsNumber(n), DontEnum | DontDelete); break; } case Sort:{ #if 0 printf("KJS Array::Sort length=%d\n", length); for ( unsigned int i = 0 ; i<length ; ++i ) printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii() ); #endif JSObject *sortFunction = NULL; if (!args[0]->isUndefined()) { sortFunction = args[0]->toObject(exec); if (!sortFunction->implementsCall()) sortFunction = NULL; } if (thisObj->classInfo() == &ArrayInstance::info) { if (sortFunction) ((ArrayInstance *)thisObj)->sort(exec, sortFunction); else ((ArrayInstance *)thisObj)->sort(exec); result = thisObj; break; } if (length == 0) { thisObj->put(exec, exec->propertyNames().length, jsNumber(0), DontEnum | DontDelete); result = thisObj; break; } // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for ( unsigned int i = 0 ; i<length-1 ; ++i ) { JSValue *iObj = thisObj->get(exec,i); unsigned int themin = i; JSValue *minObj = iObj; for ( unsigned int j = i+1 ; j<length ; ++j ) { JSValue *jObj = thisObj->get(exec,j); double cmp; if (jObj->isUndefined()) { cmp = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) } else if (minObj->isUndefined()) { cmp = -1; } else if (sortFunction) { List l; l.append(jObj); l.append(minObj); cmp = sortFunction->call(exec, exec->dynamicInterpreter()->globalObject(), l)->toNumber(exec); } else { cmp = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1; } if ( cmp < 0 ) { themin = j; minObj = jObj; } } // Swap themin and i if ( themin > i ) { //printf("KJS Array::Sort: swapping %d and %d\n", i, themin ); thisObj->put( exec, i, minObj ); thisObj->put( exec, themin, iObj ); } } #if 0 printf("KJS Array::Sort -- Resulting array:\n"); for ( unsigned int i = 0 ; i<length ; ++i ) printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii() ); #endif result = thisObj; break; } case Splice: { // 15.4.4.12 - oh boy this is huge JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty())); result = resObj; int begin = args[0]->toUInt32(exec); if ( begin < 0 ) begin = maxInt( begin + length, 0 ); else begin = minInt( begin, length ); unsigned int deleteCount = minInt( maxInt( args[1]->toUInt32(exec), 0 ), length - begin ); //printf( "Splicing from %d, deleteCount=%d \n", begin, deleteCount ); for(unsigned int k = 0; k < deleteCount; k++) { if (JSValue *v = getProperty(exec, thisObj, k+begin)) resObj->put(exec, k, v); } resObj->put(exec, exec->propertyNames().length, jsNumber(deleteCount), DontEnum | DontDelete); unsigned int additionalArgs = maxInt( args.size() - 2, 0 ); if ( additionalArgs != deleteCount ) { if ( additionalArgs < deleteCount ) { for ( unsigned int k = begin; k < length - deleteCount; ++k ) { if (JSValue *v = getProperty(exec, thisObj, k+deleteCount)) thisObj->put(exec, k+additionalArgs, v); else thisObj->deleteProperty(exec, k+additionalArgs); } for ( unsigned int k = length ; k > length - deleteCount + additionalArgs; --k ) thisObj->deleteProperty(exec, k-1); } else { for ( unsigned int k = length - deleteCount; (int)k > begin; --k ) { if (JSValue *obj = getProperty(exec, thisObj, k + deleteCount - 1)) thisObj->put(exec, k + additionalArgs - 1, obj); else thisObj->deleteProperty(exec, k+additionalArgs-1); } } } for ( unsigned int k = 0; k < additionalArgs; ++k ) { thisObj->put(exec, k+begin, args[k+2]); } thisObj->put(exec, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs), DontEnum | DontDelete); break; } case UnShift: { // 15.4.4.13 unsigned int nrArgs = args.size(); for ( unsigned int k = length; k > 0; --k ) { if (JSValue *v = getProperty(exec, thisObj, k - 1)) thisObj->put(exec, k+nrArgs-1, v); else thisObj->deleteProperty(exec, k+nrArgs-1); } for ( unsigned int k = 0; k < nrArgs; ++k ) thisObj->put(exec, k, args[k]); result = jsNumber(length + nrArgs); thisObj->put(exec, exec->propertyNames().length, result, DontEnum | DontDelete); break; } case Filter: case Map: { JSObject *eachFunction = args[0]->toObject(exec); if (!eachFunction->implementsCall()) return throwError(exec, TypeError); JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); JSObject *resultArray; if (id == Filter) resultArray = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty())); else { List args; args.append(jsNumber(length)); resultArray = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, args)); } unsigned filterIndex = 0; for (unsigned k = 0; k < length && !exec->hadException(); ++k) { PropertySlot slot; if (!thisObj->getPropertySlot(exec, k, slot)) continue; JSValue *v = slot.getValue(exec, thisObj, k); List eachArguments; eachArguments.append(v); eachArguments.append(jsNumber(k)); eachArguments.append(thisObj); JSValue *result = eachFunction->call(exec, applyThis, eachArguments); if (id == Map) resultArray->put(exec, k, result); else if (result->toBoolean(exec)) resultArray->put(exec, filterIndex++, v); } return resultArray; } case Every: case ForEach: case Some: { //Documentation for these three is available at: //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some JSObject *eachFunction = args[0]->toObject(exec); if (!eachFunction->implementsCall()) return throwError(exec, TypeError); JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); if (id == Some || id == Every) result = jsBoolean(id == Every); else result = jsUndefined(); for (unsigned k = 0; k < length && !exec->hadException(); ++k) { PropertySlot slot; if (!thisObj->getPropertySlot(exec, k, slot)) continue; List eachArguments; eachArguments.append(slot.getValue(exec, thisObj, k)); eachArguments.append(jsNumber(k)); eachArguments.append(thisObj); bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec); if (id == Every && !predicateResult) { result = jsBoolean(false); break; } if (id == Some && predicateResult) { result = jsBoolean(true); break; } } break; } case IndexOf: { // JavaScript 1.5 Extension by Mozilla // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf unsigned index = 0; double d = args[1]->toInteger(exec); if (d < 0) d += length; if (d > 0) { if (d > length) index = length; else index = static_cast<unsigned>(d); } JSValue* searchElement = args[0]; for (; index < length; ++index) { JSValue* e = getProperty(exec, thisObj, index); if (!e) continue; if (strictEqual(exec, searchElement, e)) return jsNumber(index); } return jsNumber(-1); } case LastIndexOf: { // JavaScript 1.6 Extension by Mozilla // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf int index = length - 1; double d = args[1]->toInteger(exec); if (d < 0) { d += length; if (d < 0) return jsNumber(-1); } if (d < length) index = static_cast<int>(d); JSValue* searchElement = args[0]; for (; index >= 0; --index) { JSValue* e = getProperty(exec, thisObj, index); if (!e) continue; if (strictEqual(exec, searchElement, e)) return jsNumber(index); } return jsNumber(-1); } default: assert(0); result = 0; break; } return result; }
// ES5 8.10.5 ToPropertyDescriptor static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc) { if (!in.isObject()) { throwError(exec, TypeError, "Property description must be an object."); return false; } JSObject* description = asObject(in); PropertySlot enumerableSlot; if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) { desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec)); if (exec->hadException()) return false; } PropertySlot configurableSlot; if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) { desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec)); if (exec->hadException()) return false; } JSValue value; PropertySlot valueSlot; if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) { desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value)); if (exec->hadException()) return false; } PropertySlot writableSlot; if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) { desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec)); if (exec->hadException()) return false; } PropertySlot getSlot; if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) { JSValue get = getSlot.getValue(exec, exec->propertyNames().get); if (exec->hadException()) return false; if (!get.isUndefined()) { CallData callData; if (get.getCallData(callData) == CallTypeNone) { throwError(exec, TypeError, "Getter must be a function."); return false; } } else get = JSValue(); desc.setGetter(get); } PropertySlot setSlot; if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) { JSValue set = setSlot.getValue(exec, exec->propertyNames().set); if (exec->hadException()) return false; if (!set.isUndefined()) { CallData callData; if (set.getCallData(callData) == CallTypeNone) { throwError(exec, TypeError, "Setter must be a function."); return false; } } else set = JSValue(); desc.setSetter(set); } if (!desc.isAccessorDescriptor()) return true; if (desc.value()) { throwError(exec, TypeError, "Invalid property. 'value' present on property with getter or setter."); return false; } if (desc.writablePresent()) { throwError(exec, TypeError, "Invalid property. 'writable' present on property with getter or setter."); return false; } return true; }
bool JSDOMWindow::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); // Never allow cross-domain getOwnPropertyDescriptor if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) return false; const HashEntry* entry; // We don't want any properties other than "close" and "closed" on a closed window. if (!thisObject->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() & JSC::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() & JSC::Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) { PropertySlot slot; slot.setCustom(thisObject, 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(thisObject, 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 (thisObject->impl()->frame()->tree()->scopedChild(propertyNameToAtomicString(propertyName))) { PropertySlot slot; slot.setCustom(thisObject, childFrameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } unsigned i = propertyName.asIndex(); if (i < thisObject->impl()->frame()->tree()->scopedChildCount()) { ASSERT(i != PropertyName::NotAnIndex); PropertySlot slot; slot.setCustomIndex(thisObject, i, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } // Allow shortcuts like 'Image1' instead of document.images.Image1 Document* document = thisObject->impl()->frame()->document(); if (document->isHTMLDocument()) { AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); if (atomicPropertyName && (toHTMLDocument(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { PropertySlot slot; slot.setCustom(thisObject, namedItemGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } } return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
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); }