JavaScriptCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 7 Aug 2005 06:17:49 +0000 (06:17 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 7 Aug 2005 06:17:49 +0000 (06:17 +0000)
        Reviewed by Darin.

Change over to the new PropertySlot mechanism for property
lookup. This allows the elimination of hasOwnProperty
methods. Also did some of the performance tuning enabled by this
(but not yet all the possible improvements for function calls,
assignment, ++, and so forth). And also much code cleanup.

Net result is about a 2% speedup on the JS iBench.

Also redid Geoff's fix for the chrashing applet by avoiding a NULL
prototype in the bindings code and using the default of Null()
instead.

* JavaScriptCore.xcodeproj/project.pbxproj:
        * bindings/objc/objc_runtime.h:
        * bindings/objc/objc_runtime.mm:
        (ObjcFallbackObjectImp::ObjcFallbackObjectImp):
        (ObjcFallbackObjectImp::getOwnPropertySlot):
        * bindings/runtime_array.cpp:
        (RuntimeArrayImp::lengthGetter):
        (RuntimeArrayImp::indexGetter):
        (RuntimeArrayImp::getOwnPropertySlot):
        * bindings/runtime_array.h:
        * bindings/runtime_method.cpp:
        (RuntimeMethodImp::lengthGetter):
        (RuntimeMethodImp::getOwnPropertySlot):
        * bindings/runtime_method.h:
        * bindings/runtime_object.cpp:
        (RuntimeObjectImp::RuntimeObjectImp):
        (RuntimeObjectImp::fallbackObjectGetter):
        (RuntimeObjectImp::fieldGetter):
        (RuntimeObjectImp::methodGetter):
        (RuntimeObjectImp::getOwnPropertySlot):
        * bindings/runtime_object.h:
        * bindings/runtime_root.h:
        * kjs/array_instance.h:
        * kjs/array_object.cpp:
        (ArrayInstanceImp::lengthGetter):
        (ArrayInstanceImp::getOwnPropertySlot):
        (ArrayPrototypeImp::getOwnPropertySlot):
        * kjs/array_object.h:
        * kjs/date_object.cpp:
        (DatePrototypeImp::getOwnPropertySlot):
        * kjs/date_object.h:
        * kjs/function.cpp:
        (KJS::FunctionImp::argumentsGetter):
        (KJS::FunctionImp::lengthGetter):
        (KJS::FunctionImp::getOwnPropertySlot):
        (KJS::FunctionImp::put):
        (KJS::FunctionImp::deleteProperty):
        (KJS::ArgumentsImp::mappedIndexGetter):
        (KJS::ArgumentsImp::getOwnPropertySlot):
        (KJS::ActivationImp::argumentsGetter):
        (KJS::ActivationImp::getArgumentsGetter):
        (KJS::ActivationImp::getOwnPropertySlot):
        (KJS::ActivationImp::deleteProperty):
        * kjs/function.h:
        * kjs/internal.cpp:
        (InterpreterImp::InterpreterImp):
        (InterpreterImp::initGlobalObject):
        (InterpreterImp::~InterpreterImp):
        (InterpreterImp::evaluate):
        * kjs/internal.h:
        (KJS::InterpreterImp::globalExec):
        * kjs/interpreter.cpp:
        (Interpreter::Interpreter):
        (Interpreter::createLanguageInstanceForValue):
        * kjs/interpreter.h:
        (KJS::Interpreter::argumentsIdentifier):
        (KJS::Interpreter::specialPrototypeIdentifier):
        * kjs/lookup.h:
        (KJS::staticFunctionGetter):
        (KJS::staticValueGetter):
        (KJS::getStaticPropertySlot):
        (KJS::getStaticFunctionSlot):
        (KJS::getStaticValueSlot):
        * kjs/math_object.cpp:
        (MathObjectImp::getOwnPropertySlot):
        * kjs/math_object.h:
        * kjs/nodes.cpp:
        (ResolveNode::evaluate):
        (ResolveNode::evaluateReference):
        (AccessorNode1::evaluate):
        (AccessorNode2::evaluate):
        * kjs/number_object.cpp:
        (NumberObjectImp::getOwnPropertySlot):
        * kjs/number_object.h:
        * kjs/object.cpp:
        (KJS::ObjectImp::get):
        (KJS::ObjectImp::getProperty):
        (KJS::ObjectImp::getPropertySlot):
        (KJS::ObjectImp::getOwnPropertySlot):
        (KJS::ObjectImp::put):
        (KJS::ObjectImp::hasProperty):
        (KJS::ObjectImp::hasOwnProperty):
        * kjs/object.h:
        (KJS::ObjectImp::getDirectLocation):
        (KJS::ObjectImp::getPropertySlot):
        (KJS::ObjectImp::getOwnPropertySlot):
        * kjs/object_wrapper.h: Added.
        (KJS::):
        (KJS::Object::Object):
        (KJS::Object::operator ObjectImp *):
        * kjs/property_map.cpp:
        (KJS::PropertyMap::getLocation):
        * kjs/property_map.h:
        * kjs/property_slot.cpp: Added.
        (KJS::PropertySlot::undefinedGetter):
        * kjs/property_slot.h: Added.
        (KJS::PropertySlot::isSet):
        (KJS::PropertySlot::getValue):
        (KJS::PropertySlot::setValueSlot):
        (KJS::PropertySlot::setStaticEntry):
        (KJS::PropertySlot::setCustom):
        (KJS::PropertySlot::setCustomIndex):
        (KJS::PropertySlot::setUndefined):
        (KJS::PropertySlot::slotBase):
        (KJS::PropertySlot::staticEntry):
        (KJS::PropertySlot::index):
        (KJS::PropertySlot::):
        * kjs/protect.h:
        * kjs/protected_object.h: Added.
        (KJS::ProtectedObject::ProtectedObject):
        (KJS::ProtectedObject::~ProtectedObject):
        (KJS::ProtectedObject::operator=):
        (KJS::ProtectedReference::ProtectedReference):
        (KJS::ProtectedReference::~ProtectedReference):
        (KJS::ProtectedReference::operator=):
        * kjs/reference.h:
        * kjs/reference_list.cpp:
        * kjs/regexp_object.cpp:
        (RegExpObjectImp::backrefGetter):
        (RegExpObjectImp::getOwnPropertySlot):
        * kjs/regexp_object.h:
        * kjs/string_object.cpp:
        (StringInstanceImp::lengthGetter):
        (StringInstanceImp::indexGetter):
        (StringInstanceImp::getOwnPropertySlot):
        (StringPrototypeImp::getOwnPropertySlot):
        * kjs/string_object.h:

WebCore:

        Reviewed by Darin.

Change over to the new PropertySlot mechanism for property
lookup. This allows the elimination of hasOwnProperty methods. I
also did a bunch of code cleanup and regularization of the various
property lookup methods.

        Test cases added: Added a test case for a bug I found along the way.
        * layout-tests/fast/js/string-index-overflow.html:
* layout-tests/fast/js/string-index-overflow-expected.txt:

        * khtml/ecma/kjs_binding.cpp:
        (KJS::ScriptInterpreter::createLanguageInstanceForValue):
        * khtml/ecma/kjs_binding.h:
        * khtml/ecma/kjs_css.cpp:
        (KJS::DOMCSSStyleDeclaration::indexGetter):
        (KJS::DOMCSSStyleDeclaration::cssPropertyGetter):
        (KJS::DOMCSSStyleDeclaration::getOwnPropertySlot):
        (KJS::DOMCSSStyleDeclaration::getValueProperty):
        (KJS::DOMStyleSheet::getOwnPropertySlot):
        (KJS::DOMStyleSheetList::getValueProperty):
        (KJS::DOMStyleSheetList::indexGetter):
        (KJS::DOMStyleSheetList::nameGetter):
        (KJS::DOMStyleSheetList::getOwnPropertySlot):
        (KJS::DOMMediaList::getValueProperty):
        (KJS::DOMMediaList::indexGetter):
        (KJS::DOMMediaList::getOwnPropertySlot):
        (KJS::DOMCSSStyleSheet::getValueProperty):
        (KJS::DOMCSSStyleSheet::getOwnPropertySlot):
        (KJS::DOMCSSRuleList::getValueProperty):
        (KJS::DOMCSSRuleList::indexGetter):
        (KJS::DOMCSSRuleList::getOwnPropertySlot):
        (KJS::DOMCSSRule::getOwnPropertySlot):
        (KJS::CSSRuleConstructor::getOwnPropertySlot):
        (KJS::DOMCSSValue::getValueProperty):
        (KJS::DOMCSSValue::getOwnPropertySlot):
        (KJS::CSSValueConstructor::getOwnPropertySlot):
        (KJS::DOMCSSPrimitiveValue::getValueProperty):
        (KJS::DOMCSSPrimitiveValue::getOwnPropertySlot):
        (KJS::CSSPrimitiveValueConstructor::getOwnPropertySlot):
        (KJS::DOMCSSValueList::getValueProperty):
        (KJS::DOMCSSValueList::indexGetter):
        (KJS::DOMCSSValueList::getOwnPropertySlot):
        (KJS::DOMRGBColor::getOwnPropertySlot):
        (KJS::DOMRect::getOwnPropertySlot):
        (KJS::DOMCounter::getOwnPropertySlot):
        * khtml/ecma/kjs_css.h:
        (KJS::DOMCSSStyleDeclaration::):
        (KJS::DOMCSSStyleSheet::):
        (KJS::DOMCSSRule::):
        (KJS::DOMCSSValueList::):
        * khtml/ecma/kjs_dom.cpp:
        (KJS::DOMNode::getOwnPropertySlot):
        (KJS::):
        (KJS::DOMNodeList::getValueProperty):
        (KJS::DOMNodeList::indexGetter):
        (KJS::DOMNodeList::nameGetter):
        (KJS::DOMNodeList::getOwnPropertySlot):
        (KJS::DOMNodeList::call):
        (KJS::DOMAttr::getOwnPropertySlot):
        (KJS::DOMDocument::getOwnPropertySlot):
        (KJS::DOMElement::getValueProperty):
        (KJS::DOMElement::attributeGetter):
        (KJS::DOMElement::getOwnPropertySlot):
        (KJS::DOMDocumentType::getOwnPropertySlot):
        (KJS::DOMNamedNodeMap::lengthGetter):
        (KJS::DOMNamedNodeMap::indexGetter):
        (KJS::DOMNamedNodeMap::getOwnPropertySlot):
        (KJS::DOMProcessingInstruction::getOwnPropertySlot):
        (KJS::DOMNotation::getOwnPropertySlot):
        (KJS::DOMEntity::getOwnPropertySlot):
        (KJS::NodeConstructor::getOwnPropertySlot):
        (KJS::DOMExceptionConstructor::getOwnPropertySlot):
        (KJS::DOMNamedNodesCollection::lengthGetter):
        (KJS::DOMNamedNodesCollection::indexGetter):
        (KJS::DOMNamedNodesCollection::getOwnPropertySlot):
        (KJS::DOMCharacterData::getOwnPropertySlot):
        * khtml/ecma/kjs_dom.h:
        * khtml/ecma/kjs_events.cpp:
        (KJS::EventConstructor::getOwnPropertySlot):
        (KJS::DOMEvent::getOwnPropertySlot):
        (KJS::EventExceptionConstructor::getOwnPropertySlot):
        (KJS::DOMUIEvent::getOwnPropertySlot):
        (KJS::DOMMouseEvent::getOwnPropertySlot):
        (KJS::DOMKeyboardEvent::getOwnPropertySlot):
        (KJS::MutationEventConstructor::getOwnPropertySlot):
        (KJS::DOMMutationEvent::getOwnPropertySlot):
        (KJS::DOMWheelEvent::getOwnPropertySlot):
        (KJS::Clipboard::getOwnPropertySlot):
        * khtml/ecma/kjs_events.h:
        * khtml/ecma/kjs_html.cpp:
        (KJS::HTMLDocument::namedItemGetter):
        (KJS::HTMLDocument::getValueProperty):
        (KJS::HTMLDocument::getOwnPropertySlot):
        (KJS::HTMLElement::formIndexGetter):
        (KJS::HTMLElement::formNameGetter):
        (KJS::HTMLElement::selectIndexGetter):
        (KJS::HTMLElement::framesetNameGetter):
        (KJS::HTMLElement::frameWindowPropertyGetter):
        (KJS::HTMLElement::runtimeObjectGetter):
        (KJS::HTMLElement::runtimeObjectPropertyGetter):
        (KJS::HTMLElement::getOwnPropertySlot):
        (KJS::HTMLCollection::lengthGetter):
        (KJS::HTMLCollection::indexGetter):
        (KJS::HTMLCollection::nameGetter):
        (KJS::HTMLCollection::getOwnPropertySlot):
        (KJS::HTMLSelectCollection::selectedIndexGetter):
        (KJS::HTMLSelectCollection::getOwnPropertySlot):
        (KJS::Image::getOwnPropertySlot):
        (KJS::Context2D::getOwnPropertySlot):
        (KJS::Gradient::getOwnPropertySlot):
        (KJS::ImagePattern::getOwnPropertySlot):
        * khtml/ecma/kjs_html.h:
        (KJS::HTMLCollection::toBoolean):
        * khtml/ecma/kjs_navigator.cpp:
        (KJS::Plugins::):
        (KJS::MimeTypes::):
        (KJS::Plugin::):
        (KJS::MimeType::):
        (KJS::):
        (KJS::Navigator::getOwnPropertySlot):
        (KJS::Plugins::getValueProperty):
        (KJS::Plugins::indexGetter):
        (KJS::Plugins::nameGetter):
        (KJS::Plugins::getOwnPropertySlot):
        (KJS::MimeTypes::getValueProperty):
        (KJS::MimeTypes::indexGetter):
        (KJS::MimeTypes::nameGetter):
        (KJS::MimeTypes::getOwnPropertySlot):
        (KJS::Plugin::getValueProperty):
        (KJS::Plugin::indexGetter):
        (KJS::Plugin::nameGetter):
        (KJS::Plugin::getOwnPropertySlot):
        (KJS::MimeType::getValueProperty):
        (KJS::MimeType::getOwnPropertySlot):
        * khtml/ecma/kjs_navigator.h:
        * khtml/ecma/kjs_range.cpp:
        (KJS::DOMRange::getOwnPropertySlot):
        (KJS::RangeConstructor::getOwnPropertySlot):
        * khtml/ecma/kjs_range.h:
        * khtml/ecma/kjs_traversal.cpp:
        (KJS::DOMNodeIterator::getOwnPropertySlot):
        (KJS::NodeFilterConstructor::getOwnPropertySlot):
        (KJS::DOMTreeWalker::getOwnPropertySlot):
        * khtml/ecma/kjs_traversal.h:
        * khtml/ecma/kjs_views.cpp:
        (KJS::DOMAbstractView::~DOMAbstractView):
        (KJS::DOMAbstractView::getValueProperty):
        (KJS::DOMAbstractView::getOwnPropertySlot):
        * khtml/ecma/kjs_views.h:
        * khtml/ecma/kjs_window.cpp:
        (KJS::FrameArray::):
        (KJS::FrameArray::classInfo):
        (KJS::Screen::getOwnPropertySlot):
        (KJS::Window::getValueProperty):
        (KJS::Window::childFrameGetter):
        (KJS::Window::namedFrameGetter):
        (KJS::Window::indexGetter):
        (KJS::Window::namedItemGetter):
        (KJS::Window::getOwnPropertySlot):
        (KJS::):
        (KJS::FrameArray::getValueProperty):
        (KJS::FrameArray::indexGetter):
        (KJS::FrameArray::nameGetter):
        (KJS::FrameArray::getOwnPropertySlot):
        (KJS::Location::getValueProperty):
        (KJS::Location::getOwnPropertySlot):
        (KJS::Selection::getValueProperty):
        (KJS::Selection::getOwnPropertySlot):
        (KJS::BarInfo::getValueProperty):
        (KJS::BarInfo::getOwnPropertySlot):
        (KJS::History::getOwnPropertySlot):
        * khtml/ecma/kjs_window.h:
        * khtml/ecma/xmlhttprequest.cpp:
        (KJS::XMLHttpRequest::getOwnPropertySlot):
        * khtml/ecma/xmlhttprequest.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@10076 268f45cc-cd09-0410-ab3c-d52691b4dbfc

74 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/bindings/objc/objc_runtime.h
JavaScriptCore/bindings/objc/objc_runtime.mm
JavaScriptCore/bindings/runtime_array.cpp
JavaScriptCore/bindings/runtime_array.h
JavaScriptCore/bindings/runtime_method.cpp
JavaScriptCore/bindings/runtime_method.h
JavaScriptCore/bindings/runtime_object.cpp
JavaScriptCore/bindings/runtime_object.h
JavaScriptCore/bindings/runtime_root.h
JavaScriptCore/kjs/array_instance.h
JavaScriptCore/kjs/array_object.cpp
JavaScriptCore/kjs/array_object.h
JavaScriptCore/kjs/date_object.cpp
JavaScriptCore/kjs/date_object.h
JavaScriptCore/kjs/function.cpp
JavaScriptCore/kjs/function.h
JavaScriptCore/kjs/internal.cpp
JavaScriptCore/kjs/internal.h
JavaScriptCore/kjs/interpreter.cpp
JavaScriptCore/kjs/interpreter.h
JavaScriptCore/kjs/lookup.h
JavaScriptCore/kjs/math_object.cpp
JavaScriptCore/kjs/math_object.h
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/number_object.cpp
JavaScriptCore/kjs/number_object.h
JavaScriptCore/kjs/object.cpp
JavaScriptCore/kjs/object.h
JavaScriptCore/kjs/object_wrapper.h [new file with mode: 0644]
JavaScriptCore/kjs/property_map.cpp
JavaScriptCore/kjs/property_map.h
JavaScriptCore/kjs/property_slot.cpp [new file with mode: 0644]
JavaScriptCore/kjs/property_slot.h [new file with mode: 0644]
JavaScriptCore/kjs/protect.h
JavaScriptCore/kjs/protected_object.h [new file with mode: 0644]
JavaScriptCore/kjs/reference.h
JavaScriptCore/kjs/reference_list.cpp
JavaScriptCore/kjs/regexp_object.cpp
JavaScriptCore/kjs/regexp_object.h
JavaScriptCore/kjs/string_object.cpp
JavaScriptCore/kjs/string_object.h
LayoutTests/fast/js/string-index-overflow-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/string-index-overflow.html [new file with mode: 0644]
SVGSupport/kdom/Document.h
SVGSupport/kdom/Node.h
SVGSupport/kdom/ecma/DOMLookup.h
SVGSupport/kdom/ecma/GlobalObject.cpp
SVGSupport/kdom/events/EventTarget.h
WebCore/ChangeLog-2005-08-23
WebCore/ForwardingHeaders/kjs/protected_object.h [new file with mode: 0644]
WebCore/khtml/ecma/kjs_binding.cpp
WebCore/khtml/ecma/kjs_binding.h
WebCore/khtml/ecma/kjs_css.cpp
WebCore/khtml/ecma/kjs_css.h
WebCore/khtml/ecma/kjs_dom.cpp
WebCore/khtml/ecma/kjs_dom.h
WebCore/khtml/ecma/kjs_events.cpp
WebCore/khtml/ecma/kjs_events.h
WebCore/khtml/ecma/kjs_html.cpp
WebCore/khtml/ecma/kjs_html.h
WebCore/khtml/ecma/kjs_navigator.cpp
WebCore/khtml/ecma/kjs_navigator.h
WebCore/khtml/ecma/kjs_range.cpp
WebCore/khtml/ecma/kjs_range.h
WebCore/khtml/ecma/kjs_traversal.cpp
WebCore/khtml/ecma/kjs_traversal.h
WebCore/khtml/ecma/kjs_views.cpp
WebCore/khtml/ecma/kjs_views.h
WebCore/khtml/ecma/kjs_window.cpp
WebCore/khtml/ecma/kjs_window.h
WebCore/khtml/ecma/xmlhttprequest.cpp
WebCore/khtml/ecma/xmlhttprequest.h

index 8169af1..f4d55f3 100644 (file)
@@ -1,3 +1,147 @@
+2005-08-06  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       Change over to the new PropertySlot mechanism for property
+       lookup. This allows the elimination of hasOwnProperty
+       methods. Also did some of the performance tuning enabled by this
+       (but not yet all the possible improvements for function calls,
+       assignment, ++, and so forth). And also much code cleanup.
+
+       Net result is about a 2% speedup on the JS iBench.
+       
+       Also redid Geoff's fix for the chrashing applet by avoiding a NULL
+       prototype in the bindings code and using the default of Null()
+       instead.
+        
+       * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bindings/objc/objc_runtime.h:
+        * bindings/objc/objc_runtime.mm:
+        (ObjcFallbackObjectImp::ObjcFallbackObjectImp):
+        (ObjcFallbackObjectImp::getOwnPropertySlot):
+        * bindings/runtime_array.cpp:
+        (RuntimeArrayImp::lengthGetter):
+        (RuntimeArrayImp::indexGetter):
+        (RuntimeArrayImp::getOwnPropertySlot):
+        * bindings/runtime_array.h:
+        * bindings/runtime_method.cpp:
+        (RuntimeMethodImp::lengthGetter):
+        (RuntimeMethodImp::getOwnPropertySlot):
+        * bindings/runtime_method.h:
+        * bindings/runtime_object.cpp:
+        (RuntimeObjectImp::RuntimeObjectImp):
+        (RuntimeObjectImp::fallbackObjectGetter):
+        (RuntimeObjectImp::fieldGetter):
+        (RuntimeObjectImp::methodGetter):
+        (RuntimeObjectImp::getOwnPropertySlot):
+        * bindings/runtime_object.h:
+        * bindings/runtime_root.h:
+        * kjs/array_instance.h:
+        * kjs/array_object.cpp:
+        (ArrayInstanceImp::lengthGetter):
+        (ArrayInstanceImp::getOwnPropertySlot):
+        (ArrayPrototypeImp::getOwnPropertySlot):
+        * kjs/array_object.h:
+        * kjs/date_object.cpp:
+        (DatePrototypeImp::getOwnPropertySlot):
+        * kjs/date_object.h:
+        * kjs/function.cpp:
+        (KJS::FunctionImp::argumentsGetter):
+        (KJS::FunctionImp::lengthGetter):
+        (KJS::FunctionImp::getOwnPropertySlot):
+        (KJS::FunctionImp::put):
+        (KJS::FunctionImp::deleteProperty):
+        (KJS::ArgumentsImp::mappedIndexGetter):
+        (KJS::ArgumentsImp::getOwnPropertySlot):
+        (KJS::ActivationImp::argumentsGetter):
+        (KJS::ActivationImp::getArgumentsGetter):
+        (KJS::ActivationImp::getOwnPropertySlot):
+        (KJS::ActivationImp::deleteProperty):
+        * kjs/function.h:
+        * kjs/internal.cpp:
+        (InterpreterImp::InterpreterImp):
+        (InterpreterImp::initGlobalObject):
+        (InterpreterImp::~InterpreterImp):
+        (InterpreterImp::evaluate):
+        * kjs/internal.h:
+        (KJS::InterpreterImp::globalExec):
+        * kjs/interpreter.cpp:
+        (Interpreter::Interpreter):
+        (Interpreter::createLanguageInstanceForValue):
+        * kjs/interpreter.h:
+        (KJS::Interpreter::argumentsIdentifier):
+        (KJS::Interpreter::specialPrototypeIdentifier):
+        * kjs/lookup.h:
+        (KJS::staticFunctionGetter):
+        (KJS::staticValueGetter):
+        (KJS::getStaticPropertySlot):
+        (KJS::getStaticFunctionSlot):
+        (KJS::getStaticValueSlot):
+        * kjs/math_object.cpp:
+        (MathObjectImp::getOwnPropertySlot):
+        * kjs/math_object.h:
+        * kjs/nodes.cpp:
+        (ResolveNode::evaluate):
+        (ResolveNode::evaluateReference):
+        (AccessorNode1::evaluate):
+        (AccessorNode2::evaluate):
+        * kjs/number_object.cpp:
+        (NumberObjectImp::getOwnPropertySlot):
+        * kjs/number_object.h:
+        * kjs/object.cpp:
+        (KJS::ObjectImp::get):
+        (KJS::ObjectImp::getProperty):
+        (KJS::ObjectImp::getPropertySlot):
+        (KJS::ObjectImp::getOwnPropertySlot):
+        (KJS::ObjectImp::put):
+        (KJS::ObjectImp::hasProperty):
+        (KJS::ObjectImp::hasOwnProperty):
+        * kjs/object.h:
+        (KJS::ObjectImp::getDirectLocation):
+        (KJS::ObjectImp::getPropertySlot):
+        (KJS::ObjectImp::getOwnPropertySlot):
+        * kjs/object_wrapper.h: Added.
+        (KJS::):
+        (KJS::Object::Object):
+        (KJS::Object::operator ObjectImp *):
+        * kjs/property_map.cpp:
+        (KJS::PropertyMap::getLocation):
+        * kjs/property_map.h:
+        * kjs/property_slot.cpp: Added.
+        (KJS::PropertySlot::undefinedGetter):
+        * kjs/property_slot.h: Added.
+        (KJS::PropertySlot::isSet):
+        (KJS::PropertySlot::getValue):
+        (KJS::PropertySlot::setValueSlot):
+        (KJS::PropertySlot::setStaticEntry):
+        (KJS::PropertySlot::setCustom):
+        (KJS::PropertySlot::setCustomIndex):
+        (KJS::PropertySlot::setUndefined):
+        (KJS::PropertySlot::slotBase):
+        (KJS::PropertySlot::staticEntry):
+        (KJS::PropertySlot::index):
+        (KJS::PropertySlot::):
+        * kjs/protect.h:
+        * kjs/protected_object.h: Added.
+        (KJS::ProtectedObject::ProtectedObject):
+        (KJS::ProtectedObject::~ProtectedObject):
+        (KJS::ProtectedObject::operator=):
+        (KJS::ProtectedReference::ProtectedReference):
+        (KJS::ProtectedReference::~ProtectedReference):
+        (KJS::ProtectedReference::operator=):
+        * kjs/reference.h:
+        * kjs/reference_list.cpp:
+        * kjs/regexp_object.cpp:
+        (RegExpObjectImp::backrefGetter):
+        (RegExpObjectImp::getOwnPropertySlot):
+        * kjs/regexp_object.h:
+        * kjs/string_object.cpp:
+        (StringInstanceImp::lengthGetter):
+        (StringInstanceImp::indexGetter):
+        (StringInstanceImp::getOwnPropertySlot):
+        (StringPrototypeImp::getOwnPropertySlot):
+        * kjs/string_object.h:
+
 2005-08-05  Adele Peterson  <adele@apple.com>
 
         Reviewed by Darin.
index 1bb9303..947a7fa 100644 (file)
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
+               65305EAF08A58DDE00F31E73 /* protected_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 65305EAE08A58DDE00F31E73 /* protected_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               65305EB008A58E0900F31E73 /* protected_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 65305EAE08A58DDE00F31E73 /* protected_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               6539AACB08A3225A00223EE2 /* object_wrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 6539AACA08A3225A00223EE2 /* object_wrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               65621E6D089E859700760F35 /* property_slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65621E6B089E859700760F35 /* property_slot.cpp */; };
+               65621E6E089E859700760F35 /* property_slot.h in Headers */ = {isa = PBXBuildFile; fileRef = 65621E6C089E859700760F35 /* property_slot.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               65621E6F089E85D300760F35 /* property_slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65621E6B089E859700760F35 /* property_slot.cpp */; };
+               65621E70089E85D300760F35 /* property_slot.h in Headers */ = {isa = PBXBuildFile; fileRef = 65621E6C089E859700760F35 /* property_slot.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               65BBAEE008A329B300357728 /* object_wrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 6539AACA08A3225A00223EE2 /* object_wrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B400822A1C700736975 /* array_object.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A84E0255597D01FF60F7 /* array_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B420822A1C700736975 /* collector.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8530255597D01FF60F7 /* collector.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B430822A1C700736975 /* date_object.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8560255597D01FF60F7 /* date_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
                651BDC78080F10CC00F10856 /* fast_malloc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fast_malloc.h; sourceTree = "<group>"; };
                651F6412039D5B5F0078395C /* dtoa.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dtoa.cpp; sourceTree = "<group>"; };
                651F6413039D5B5F0078395C /* dtoa.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dtoa.h; sourceTree = "<group>"; };
+               65305EAE08A58DDE00F31E73 /* protected_object.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = protected_object.h; sourceTree = "<group>"; };
+               6539AACA08A3225A00223EE2 /* object_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = object_wrapper.h; sourceTree = "<group>"; };
                65417205039E02E70058BFEB /* get.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = get.c; path = pcre/get.c; sourceTree = "<group>"; };
                65417206039E02E70058BFEB /* maketables.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = maketables.c; path = pcre/maketables.c; sourceTree = "<group>"; };
                65417207039E02E70058BFEB /* pcre.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = pcre.c; path = pcre/pcre.c; sourceTree = "<group>"; };
                65417217039E0B280058BFEB /* pcre-config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "pcre-config.h"; path = "pcre/pcre-config.h"; sourceTree = "<group>"; };
                6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
                6560A63D04B3B69F008AE952 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
+               65621E6B089E859700760F35 /* property_slot.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = property_slot.cpp; sourceTree = "<group>"; };
+               65621E6C089E859700760F35 /* property_slot.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = property_slot.h; sourceTree = "<group>"; };
                65AB004806261CBA0076DE63 /* interpreter_map.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter_map.cpp; sourceTree = "<group>"; };
                65AB004906261CBA0076DE63 /* interpreter_map.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = interpreter_map.h; sourceTree = "<group>"; };
                65C02FBB0637462A003E7EE6 /* protect.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = protect.h; sourceTree = "<group>"; };
                08FB77AEFE84172EC02AAC07 /* Classes */ = {
                        isa = PBXGroup;
                        children = (
+                               65305EAE08A58DDE00F31E73 /* protected_object.h */,
+                               6539AACA08A3225A00223EE2 /* object_wrapper.h */,
+                               65621E6B089E859700760F35 /* property_slot.cpp */,
+                               65621E6C089E859700760F35 /* property_slot.h */,
                                938772E5038BFE19008635CE /* array_instance.h */,
                                650B68D80639033F009D42DE /* protected_values.cpp */,
                                650B68D90639033F009D42DE /* protected_values.h */,
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               65305EAF08A58DDE00F31E73 /* protected_object.h in Headers */,
                                932F5B400822A1C700736975 /* array_object.h in Headers */,
                                932F5B420822A1C700736975 /* collector.h in Headers */,
                                932F5B430822A1C700736975 /* date_object.h in Headers */,
                                932F5B8E0822A1C700736975 /* npruntime_impl.h in Headers */,
                                932F5B8F0822A1C700736975 /* fast_malloc.h in Headers */,
                                932FC11D0824A6A3005B3C75 /* create_hash_table in Headers */,
+                               65621E6E089E859700760F35 /* property_slot.h in Headers */,
+                               6539AACB08A3225A00223EE2 /* object_wrapper.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               65305EB008A58E0900F31E73 /* protected_object.h in Headers */,
                                A85D81F8087B2822006A9172 /* array_object.h in Headers */,
                                A85D81F9087B2822006A9172 /* collector.h in Headers */,
                                A85D81FA087B2822006A9172 /* date_object.h in Headers */,
                                A85D8204087B2822006A9172 /* nodes.h in Headers */,
                                A85D8205087B2822006A9172 /* number_object.h in Headers */,
                                A85D8206087B2822006A9172 /* object_object.h in Headers */,
+                               65BBAEE008A329B300357728 /* object_wrapper.h in Headers */,
                                A85D8207087B2822006A9172 /* object.h in Headers */,
                                A85D8208087B2822006A9172 /* operations.h in Headers */,
                                A85D8209087B2822006A9172 /* property_map.h in Headers */,
                                A85D823C087B2822006A9172 /* npruntime_priv.h in Headers */,
                                A85D823D087B2822006A9172 /* npruntime_impl.h in Headers */,
                                A85D823E087B2822006A9172 /* fast_malloc.h in Headers */,
+                               65621E70089E85D300760F35 /* property_slot.h in Headers */,
                                A85D823F087B2822006A9172 /* create_hash_table in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                                932F5BCF0822A1C700736975 /* jni_objc.mm in Sources */,
                                932F5BD00822A1C700736975 /* softlinking.c in Sources */,
                                932F5BD10822A1C700736975 /* fast_malloc.cpp in Sources */,
+                               65621E6D089E859700760F35 /* property_slot.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                A85D827E087B2822006A9172 /* jni_objc.mm in Sources */,
                                A85D827F087B2822006A9172 /* softlinking.c in Sources */,
                                A85D8280087B2822006A9172 /* fast_malloc.cpp in Sources */,
+                               65621E6F089E85D300760F35 /* property_slot.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 744e01e..69a1ef8 100644 (file)
@@ -169,7 +169,7 @@ public:
 
     const ClassInfo *classInfo() const { return &info; }
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
 
     virtual void put(ExecState *exec, const Identifier &propertyName,
                      const Value &value, int attr = None);
@@ -179,12 +179,7 @@ public:
     virtual bool implementsCall() const;
     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
 
-    virtual bool hasOwnProperty(ExecState *exec,
-                            const Identifier &propertyName) const;
-
-
-    virtual bool deleteProperty(ExecState *exec,
-                                const Identifier &propertyName);
+    virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
 
     virtual Value defaultValue(ExecState *exec, Type hint) const;
 
index 1168934..b36b007 100644 (file)
@@ -262,16 +262,15 @@ ObjcFallbackObjectImp::ObjcFallbackObjectImp(ObjectImp *proto)
 }
 
 ObjcFallbackObjectImp::ObjcFallbackObjectImp(ObjcInstance *i, const KJS::Identifier propertyName)
-    : ObjectImp ((ObjectImp *)0)
 {
     _instance = i;
     _item = propertyName;
 }
 
-bool ObjcFallbackObjectImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool ObjcFallbackObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
     // keep the prototype from getting called instead of just returning false
-    result = Undefined();
+    slot.setUndefined(this);
     return true;
 }
 
@@ -335,12 +334,6 @@ Value ObjcFallbackObjectImp::call(ExecState *exec, Object &thisObj, const List &
     return result;
 }
 
-bool ObjcFallbackObjectImp::hasOwnProperty(ExecState *exec,
-                         const Identifier &propertyName) const
-{
-    return false;
-}
-
 bool ObjcFallbackObjectImp::deleteProperty(ExecState *exec,
                             const Identifier &propertyName)
 {
index 113be46..f86fdc1 100644 (file)
@@ -43,34 +43,45 @@ RuntimeArrayImp::~RuntimeArrayImp()
     delete _array;
 }
 
-bool RuntimeArrayImp::getOwnProperty(ExecState *exec, const Identifier &propertyName, Value& result) const
+Value RuntimeArrayImp::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    RuntimeArrayImp *thisObj = static_cast<RuntimeArrayImp *>(slot.slotBase());
+    return Number(thisObj->getLength());
+}
+
+Value RuntimeArrayImp::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    RuntimeArrayImp *thisObj = static_cast<RuntimeArrayImp *>(slot.slotBase());
+    return thisObj->getConcreteArray()->valueAt(exec, slot.index());
+}
+
+bool RuntimeArrayImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (propertyName == lengthPropertyName) {
-        result = Number(getLength());
+        slot.setCustom(this, lengthGetter);
         return true;
     }
     
     bool ok;
     unsigned index = propertyName.toArrayIndex(&ok);
     if (ok) {
-        if (index >= getLength())
-            result =  Undefined();
-        else
-            result = getConcreteArray()->valueAt(exec, index);
-        return true;
+        if (index < getLength()) {
+            slot.setCustomIndex(this, index, indexGetter);
+            return true;
+        }
     }
     
-    return ArrayInstanceImp::getOwnProperty(exec, propertyName, result);
+    return ArrayInstanceImp::getOwnPropertySlot(exec, propertyName, slot);
 }
 
-bool RuntimeArrayImp::getOwnProperty(ExecState *exec, unsigned index, Value& result) const
+bool RuntimeArrayImp::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot)
 {
-    if (index >= getLength())
-        result = Undefined();
-    else
-        result = getConcreteArray()->valueAt(exec, index);
+    if (index < getLength()) {
+        slot.setCustomIndex(this, index, indexGetter);
+        return true;
+    }
     
-    return true;
+    return ArrayInstanceImp::getOwnPropertySlot(exec, index, slot);
 }
 
 void RuntimeArrayImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
@@ -102,30 +113,6 @@ void RuntimeArrayImp::put(ExecState *exec, unsigned index, const Value &value, i
     getConcreteArray()->setValueAt(exec, index, value);
 }
 
-
-bool RuntimeArrayImp::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
-{
-    if (propertyName == lengthPropertyName)
-        return true;
-    
-    bool ok;
-    unsigned index = propertyName.toArrayIndex(&ok);
-    if (ok) {
-        if (index >= getLength())
-            return false;
-        return true;
-    }
-    
-    return ObjectImp::hasOwnProperty(exec, propertyName);
-}
-
-bool RuntimeArrayImp::hasOwnProperty(ExecState *exec, unsigned index) const
-{
-    if (index >= getLength())
-        return false;
-    return true;
-}
-
 bool RuntimeArrayImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
 {
     return false;
index 324a379..2224ff4 100644 (file)
@@ -37,13 +37,11 @@ public:
     RuntimeArrayImp(ExecState *exec, Bindings::Array *i);
     ~RuntimeArrayImp();
     
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
-    virtual bool getOwnProperty(ExecState *exec, unsigned index, Value& result) const ;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    virtual bool getOwnPropertySlot(ExecState *, unsigned, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None);
     virtual void put(ExecState *exec, unsigned propertyName, const Value &value, int attr = None);
     
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
-    virtual bool hasOwnProperty(ExecState *exec, unsigned propertyName) const;
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
     virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
     
@@ -56,6 +54,9 @@ public:
     static const ClassInfo info;
 
 private:
+    static Value lengthGetter(ExecState *, const Identifier&, const PropertySlot&);
+    static Value indexGetter(ExecState *, const Identifier&, const PropertySlot&);
+
     Bindings::Array *_array;
 };
     
index 74c2866..7161e43 100644 (file)
@@ -40,19 +40,27 @@ RuntimeMethodImp::~RuntimeMethodImp()
 {
 }
 
-bool RuntimeMethodImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value RuntimeMethodImp::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    RuntimeMethodImp *thisObj = static_cast<RuntimeMethodImp *>(slot.slotBase());
+
+    // Ick!  There may be more than one method with this name.  Arbitrarily
+    // just pick the first method.  The fundamental problem here is that 
+    // JavaScript doesn't have the notion of method overloading and
+    // Java does.
+    // FIXME: a better solution might be to give the maximum number of parameters
+    // of any method
+    return Number(thisObj->_methodList.methodAt(0)->numParameters());
+}
+
+bool RuntimeMethodImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
 {
-    // Compute length of parameters.
     if (propertyName == lengthPropertyName) {
-        // Ick!  There may be more than one method with this name.  Arbitrarily
-        // just pick the first method.  The fundamental problem here is that 
-        // JavaScript doesn't have the notion of method overloading and
-        // Java does.
-        result = Number(_methodList.methodAt(0)->numParameters());
-        return result;
+        slot.setCustom(this, lengthGetter);
+        return true;
     }
     
-    return FunctionImp::getOwnProperty(exec, propertyName, result);
+    return FunctionImp::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 bool RuntimeMethodImp::implementsCall() const
index 3fc4dbb..99f7f27 100644 (file)
@@ -38,7 +38,7 @@ public:
     
     virtual ~RuntimeMethodImp();
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
 
     virtual bool implementsCall() const;
     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
@@ -48,6 +48,8 @@ public:
     virtual Completion execute(ExecState *exec);
 
 private:
+    static Value lengthGetter(ExecState *, const Identifier&, const PropertySlot&);
+
     Bindings::MethodList _methodList;
 };
 
index 3a54e77..64595d7 100644 (file)
@@ -54,37 +54,87 @@ RuntimeObjectImp::~RuntimeObjectImp()
     }
 }
 
-RuntimeObjectImp::RuntimeObjectImp(Bindings::Instance *i, bool oi) : ObjectImp ((ObjectImp *)0)
+RuntimeObjectImp::RuntimeObjectImp(Bindings::Instance *i, bool oi)
 {
     ownsInstance = oi;
     instance = i;
 }
 
-bool RuntimeObjectImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value RuntimeObjectImp::fallbackObjectGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
+    Bindings::Instance *instance = thisObj->instance;
+
+    instance->begin();
+
+    Class *aClass = instance->getClass();
+    Value result = aClass->fallbackObject(exec, instance, propertyName);
+
+    instance->end();
+            
+    return result;
+}
+
+Value RuntimeObjectImp::fieldGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
+    Bindings::Instance *instance = thisObj->instance;
+
+    instance->begin();
+
+    Class *aClass = instance->getClass();
+    Field *aField = aClass->fieldNamed(propertyName.ascii(), instance);
+    Value result = instance->getValueOfField(exec, aField); 
+    
+    instance->end();
+            
+    return result;
+}
+
+Value RuntimeObjectImp::methodGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
+    Bindings::Instance *instance = thisObj->instance;
+
+    instance->begin();
+
+    Class *aClass = instance->getClass();
+    MethodList methodList = aClass->methodsNamed(propertyName.ascii(), instance);
+    Value result = Object(new RuntimeMethodImp(exec, propertyName, methodList));
+
+    instance->end();
+            
+    return result;
+}
+
+bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
     instance->begin();
     
     Class *aClass = instance->getClass();
     
     if (aClass) {
-        // See if the instance have a field with the specified name.
+        // See if the instance has a field with the specified name.
         Field *aField = aClass->fieldNamed(propertyName.ascii(), instance);
         if (aField) {
-            result = instance->getValueOfField(exec, aField); 
+            slot.setCustom(this, fieldGetter);
+            instance->end();
             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.ascii(), instance);
             if (methodList.length() > 0) {
-                result = Object(new RuntimeMethodImp(exec, propertyName, methodList));
+                slot.setCustom(this, methodGetter);
+                instance->end();
                 return true;
             }
         }
        
-        if (result.type() == UndefinedType) {
-            // Try a fallback object.
-            result = aClass->fallbackObject(exec, instance, propertyName);
+        // Try a fallback object.
+        if (!aClass->fallbackObject(exec, instance, propertyName).type() != UndefinedType) {
+            slot.setCustom(this, fallbackObjectGetter);
+            instance->end();
             return true;
         }
     }
@@ -130,29 +180,6 @@ bool RuntimeObjectImp::canPut(ExecState *exec, const Identifier &propertyName) c
     return result;
 }
 
-bool RuntimeObjectImp::hasOwnProperty(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::deleteProperty(ExecState *exec,
                             const Identifier &propertyName)
 {
index 07bf9ab..7be49e0 100644 (file)
@@ -41,17 +41,13 @@ public:
 
     const ClassInfo *classInfo() const { return &info; }
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
 
     virtual void put(ExecState *exec, const Identifier &propertyName,
                      const Value &value, int attr = None);
 
     virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
 
-    virtual bool hasOwnProperty(ExecState *exec,
-                            const Identifier &propertyName) const;
-
-
     virtual bool deleteProperty(ExecState *exec,
                                 const Identifier &propertyName);
 
@@ -66,6 +62,10 @@ public:
     static const ClassInfo info;
 
 private:
+    static Value fallbackObjectGetter(ExecState *, const Identifier&, const PropertySlot&);
+    static Value fieldGetter(ExecState *, const Identifier&, const PropertySlot&);
+    static Value methodGetter(ExecState *, const Identifier&, const PropertySlot&);
+
     Bindings::Instance *instance;
     bool ownsInstance;
 };
index 0f1516b..f23da13 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <JavaScriptCore/interpreter.h>
 #include <JavaScriptCore/object.h>
+#include <JavaScriptCore/protect.h>
 #include <JavaScriptCore/jni_jsobject.h>
 
 namespace KJS {
index 72ed6e2..b185d39 100644 (file)
@@ -33,12 +33,10 @@ namespace KJS {
     ArrayInstanceImp(ObjectImp *proto, const List &initialValues);
     ~ArrayInstanceImp();
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
-    virtual bool getOwnProperty(ExecState *exec, unsigned index, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    virtual bool getOwnPropertySlot(ExecState *, unsigned, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None);
     virtual void put(ExecState *exec, unsigned propertyName, const Value &value, int attr = None);
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
-    virtual bool hasOwnProperty(ExecState *exec, unsigned propertyName) const;
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
     virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
     virtual ReferenceList propList(ExecState *exec, bool recursive);
@@ -54,6 +52,8 @@ namespace KJS {
     void sort(ExecState *exec, Object &compareFunction);
     
   private:
+    static Value lengthGetter(ExecState *, const Identifier&, const PropertySlot&);
+
     void setLength(unsigned newLength, ExecState *exec);
     
     unsigned pushUndefinedObjectsToEnd(ExecState *exec);
index 1591ba4..50b783c 100644 (file)
@@ -70,10 +70,15 @@ ArrayInstanceImp::~ArrayInstanceImp()
   free(storage);
 }
 
-bool ArrayInstanceImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value ArrayInstanceImp::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  return Number(static_cast<ArrayInstanceImp *>(slot.slotBase())->length);
+}
+
+bool ArrayInstanceImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
   if (propertyName == lengthPropertyName) {
-    result = Number(length);
+    slot.setCustom(this, lengthGetter);
     return true;
   }
 
@@ -86,16 +91,16 @@ bool ArrayInstanceImp::getOwnProperty(ExecState *exec, const Identifier& propert
       ValueImp *v = storage[index];
       if (!v || v == UndefinedImp::staticUndefined)
         return false;
-
-      result = Value(v);
+      
+      slot.setValueSlot(this, &storage[index]);
       return true;
     }
   }
 
-  return ObjectImp::getOwnProperty(exec, propertyName, result);
+  return ObjectImp::getOwnPropertySlot(exec, propertyName, slot);
 }
 
-bool ArrayInstanceImp::getOwnProperty(ExecState *exec, unsigned index, Value& result) const
+bool ArrayInstanceImp::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot)
 {
   if (index >= length)
     return false;
@@ -103,12 +108,12 @@ bool ArrayInstanceImp::getOwnProperty(ExecState *exec, unsigned index, Value& re
     ValueImp *v = storage[index];
     if (!v || v == UndefinedImp::staticUndefined)
       return false;
-
-    result = Value(v);
+    
+    slot.setValueSlot(this, &storage[index]);
     return true;
   }
-  
-  return ObjectImp::getOwnProperty(exec, Identifier::from(index), result);
+
+  return ObjectImp::getOwnPropertySlot(exec, index, slot);
 }
 
 // Special implementation of [[Put]] - see ECMA 15.4.5.1
@@ -148,37 +153,6 @@ void ArrayInstanceImp::put(ExecState *exec, unsigned index, const Value &value,
   ObjectImp::put(exec, Identifier::from(index), value, attr);
 }
 
-bool ArrayInstanceImp::hasOwnProperty(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::hasOwnProperty(exec, propertyName);
-}
-
-bool ArrayInstanceImp::hasOwnProperty(ExecState *exec, unsigned index) const
-{
-  if (index >= length)
-    return false;
-  if (index < storageLength) {
-    ValueImp *v = storage[index];
-    return v && v != UndefinedImp::staticUndefined;
-  }
-  
-  return ObjectImp::hasOwnProperty(exec, Identifier::from(index));
-}
-
 bool ArrayInstanceImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
 {
   if (propertyName == lengthPropertyName)
@@ -428,9 +402,9 @@ ArrayPrototypeImp::ArrayPrototypeImp(ExecState *exec,
   setInternalValue(Null());
 }
 
-bool ArrayPrototypeImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool ArrayPrototypeImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnFunction<ArrayProtoFuncImp, ArrayInstanceImp>(exec, propertyName, &arrayTable, this, result);
+  return getStaticFunctionSlot<ArrayProtoFuncImp, ArrayInstanceImp>(exec, &arrayTable, this, propertyName, slot);
 }
 
 // ------------------------------ ArrayProtoFuncImp ----------------------------
index 8dec59e..a54db94 100644 (file)
@@ -31,7 +31,7 @@ namespace KJS {
   public:
     ArrayPrototypeImp(ExecState *exec,
                       ObjectPrototypeImp *objProto);
-    bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
   };
index 02ee549..454cd93 100644 (file)
@@ -490,9 +490,9 @@ DatePrototypeImp::DatePrototypeImp(ExecState *,
   // The constructor will be added later, after DateObjectImp has been built
 }
 
-bool DatePrototypeImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DatePrototypeImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnFunction<DateProtoFuncImp, ObjectImp>(exec, propertyName, &dateTable, this, result);
+  return getStaticFunctionSlot<DateProtoFuncImp, ObjectImp>(exec, &dateTable, this, propertyName, slot);
 }
 
 // ------------------------------ DateProtoFuncImp -----------------------------
index 42b9ba6..dfe8a78 100644 (file)
@@ -46,7 +46,7 @@ namespace KJS {
   class DatePrototypeImp : public DateInstanceImp {
   public:
     DatePrototypeImp(ExecState *exec, ObjectPrototypeImp *objectProto);
-    bool getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const;
+    bool getOwnPropertySlot(ExecState *, const Identifier &, PropertySlot&);
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
   };
index c20cadd..0075871 100644 (file)
@@ -208,54 +208,58 @@ void FunctionImp::processVarDecls(ExecState */*exec*/)
 {
 }
 
-bool FunctionImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value FunctionImp::argumentsGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  FunctionImp *thisObj = static_cast<FunctionImp *>(slot.slotBase());
+  ContextImp *context = exec->_context;
+  while (context) {
+    if (context->function() == thisObj) {
+      return static_cast<ActivationImp *>(context->activationObject())->get(exec, propertyName);
+    }
+    context = context->callingContext();
+  }
+  return Null();
+}
+
+Value FunctionImp::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  FunctionImp *thisObj = static_cast<FunctionImp *>(slot.slotBase());
+  const Parameter *p = thisObj->param;
+  int count = 0;
+  while (p) {
+    ++count;
+    p = p->next;
+  }
+  return Number(count);
+}
+
+bool FunctionImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
     // Find the arguments from the closest context.
-    if (propertyName == argumentsPropertyName) {
-        ContextImp *context = exec->_context;
-        while (context) {
-          if (context->function() == this) {
-            result = static_cast<ActivationImp *>(context->activationObject())->get(exec, propertyName);
-            return true;
-          }
-          context = context->callingContext();
-        }
-        result = Null();
+    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier()) {
+        slot.setCustom(this, argumentsGetter);
         return true;
     }
     
     // Compute length of parameters.
     if (propertyName == lengthPropertyName) {
-        const Parameter * p = param;
-        int count = 0;
-        while (p) {
-            ++count;
-            p = p->next;
-        }
-        result = Number(count);
+        slot.setCustom(this, lengthGetter);
         return true;
     }
     
-    return InternalFunctionImp::getOwnProperty(exec, propertyName, result);
+    return InternalFunctionImp::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 void FunctionImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
 {
-    if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
+    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier() || propertyName == lengthPropertyName)
         return;
     InternalFunctionImp::put(exec, propertyName, value, attr);
 }
 
-bool FunctionImp::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
-{
-    if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
-        return true;
-    return InternalFunctionImp::hasOwnProperty(exec, propertyName);
-}
-
 bool FunctionImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
 {
-    if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
+    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier() || propertyName == lengthPropertyName)
         return false;
     return InternalFunctionImp::deleteProperty(exec, propertyName);
 }
@@ -449,14 +453,20 @@ void ArgumentsImp::mark()
     _activationObject->mark();
 }
 
-bool ArgumentsImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value ArgumentsImp::mappedIndexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  ArgumentsImp *thisObj = static_cast<ArgumentsImp *>(slot.slotBase());
+  return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);
+}
+
+bool ArgumentsImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
   if (indexToNameMap.isMapped(propertyName)) {
-    result = _activationObject->get(exec, indexToNameMap[propertyName]);
+    slot.setCustom(this, mappedIndexGetter);
     return true;
   }
 
-  return ObjectImp::getOwnProperty(exec, propertyName, result);
+  return ObjectImp::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 void ArgumentsImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
@@ -478,14 +488,6 @@ bool ArgumentsImp::deleteProperty(ExecState *exec, const Identifier &propertyNam
   }
 }
 
-bool ArgumentsImp::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
-{
-  if (indexToNameMap.isMapped(propertyName))
-    return true;
-  
-  return ObjectImp::hasOwnProperty(exec, propertyName);
-}
-
 // ------------------------------ ActivationImp --------------------------------
 
 const ClassInfo ActivationImp::info = {"Activation", 0, 0, 0};
@@ -498,34 +500,39 @@ ActivationImp::ActivationImp(FunctionImp *function, const List &arguments)
   // FIXME: Do we need to support enumerating the arguments property?
 }
 
-bool ActivationImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value ActivationImp::argumentsGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  ActivationImp *thisObj = static_cast<ActivationImp *>(slot.slotBase());
+
+  // default: return builtin arguments array
+  if (!thisObj->_argumentsObject)
+    thisObj->createArgumentsObject(exec);
+  
+  return Value(thisObj->_argumentsObject);
+}
+
+PropertySlot::GetValueFunc ActivationImp::getArgumentsGetter()
+{
+  return ActivationImp::argumentsGetter;
+}
+
+bool ActivationImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
     // do this first so property map arguments property wins over the below
-    if (ObjectImp::getOwnProperty(exec, propertyName, result))
+    if (ObjectImp::getOwnPropertySlot(exec, propertyName, slot))
         return true;
 
-    if (propertyName == argumentsPropertyName) {
-        // default: return builtin arguments array
-        if (!_argumentsObject)
-            createArgumentsObject(exec);
-
-        result = Value(_argumentsObject);
+    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier()) {
+        slot.setCustom(this, getArgumentsGetter());
         return true;
     }
 
     return false;
 }
 
-bool ActivationImp::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
-{
-    if (propertyName == argumentsPropertyName)
-        return true;
-    return ObjectImp::hasOwnProperty(exec, propertyName);
-}
-
 bool ActivationImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
 {
-    if (propertyName == argumentsPropertyName)
+    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier())
         return false;
     return ObjectImp::deleteProperty(exec, propertyName);
 }
index 56a0a54..299c4b2 100644 (file)
@@ -42,9 +42,8 @@ namespace KJS {
     FunctionImp(ExecState *exec, const Identifier &n = Identifier::null());
     virtual ~FunctionImp();
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier &, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None);
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
 
     virtual bool implementsCall() const;
@@ -66,6 +65,9 @@ namespace KJS {
     Identifier ident;
 
   private:
+    static Value argumentsGetter(ExecState *, const Identifier &, const PropertySlot&);
+    static Value lengthGetter(ExecState *, const Identifier &, const PropertySlot&);
+
     void processParameters(ExecState *exec, const List &);
     virtual void processVarDecls(ExecState *exec);
   };
@@ -109,14 +111,15 @@ namespace KJS {
   public:
     ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args, ActivationImp *act);
     virtual void mark();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier &, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName,
                      const Value &value, int attr = None);
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
   private:
+    static Value mappedIndexGetter(ExecState *exec, const Identifier &, const PropertySlot& slot);
+
     ActivationImp *_activationObject; 
     mutable IndexToNameMap indexToNameMap;
   };
@@ -125,8 +128,7 @@ namespace KJS {
   public:
     ActivationImp(FunctionImp *function, const List &arguments);
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
+    virtual bool getOwnPropertySlot(ExecState *exec, const Identifier &, PropertySlot&);
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
 
     virtual const ClassInfo *classInfo() const { return &info; }
@@ -135,6 +137,8 @@ namespace KJS {
     virtual void mark();
 
   private:
+    static PropertySlot::GetValueFunc getArgumentsGetter();
+    static Value argumentsGetter(ExecState *exec, const Identifier &, const PropertySlot& slot);
     void createArgumentsObject(ExecState *exec) const;
     
     FunctionImp *_function;
index dd1497f..22ba81d 100644 (file)
@@ -497,7 +497,8 @@ void InterpreterImp::globalClear()
 }
 
 InterpreterImp::InterpreterImp(Interpreter *interp, const Object &glob)
-    : _context(0)
+  : globExec(interp, 0)
+  , _context(0)
 {
   // add this interpreter to the global chain
   // as a root set for garbage collection
@@ -517,7 +518,6 @@ InterpreterImp::InterpreterImp(Interpreter *interp, const Object &glob)
   InterpreterMap::setInterpreterForGlobalObject(this, glob.imp());
 
   global = glob;
-  globExec = new ExecState(m_interpreter,0);
   dbg = 0;
   m_compatMode = Interpreter::NativeMode;
 
@@ -549,131 +549,129 @@ void InterpreterImp::unlock()
   
   // Contructor prototype objects (Object.prototype, Array.prototype etc)
 
-  FunctionPrototypeImp *funcProto = new FunctionPrototypeImp(globExec);
+  FunctionPrototypeImp *funcProto = new FunctionPrototypeImp(&globExec);
   b_FunctionPrototype = Object(funcProto);
-  ObjectPrototypeImp *objProto = new ObjectPrototypeImp(globExec,funcProto);
+  ObjectPrototypeImp *objProto = new ObjectPrototypeImp(&globExec, funcProto);
   b_ObjectPrototype = Object(objProto);
   funcProto->setPrototype(b_ObjectPrototype);
 
-  ArrayPrototypeImp *arrayProto = new ArrayPrototypeImp(globExec,objProto);
+  ArrayPrototypeImp *arrayProto = new ArrayPrototypeImp(&globExec, objProto);
   b_ArrayPrototype = Object(arrayProto);
-  StringPrototypeImp *stringProto = new StringPrototypeImp(globExec,objProto);
+  StringPrototypeImp *stringProto = new StringPrototypeImp(&globExec, objProto);
   b_StringPrototype = Object(stringProto);
-  BooleanPrototypeImp *booleanProto = new BooleanPrototypeImp(globExec,objProto,funcProto);
+  BooleanPrototypeImp *booleanProto = new BooleanPrototypeImp(&globExec, objProto, funcProto);
   b_BooleanPrototype = Object(booleanProto);
-  NumberPrototypeImp *numberProto = new NumberPrototypeImp(globExec,objProto,funcProto);
+  NumberPrototypeImp *numberProto = new NumberPrototypeImp(&globExec, objProto, funcProto);
   b_NumberPrototype = Object(numberProto);
-  DatePrototypeImp *dateProto = new DatePrototypeImp(globExec,objProto);
+  DatePrototypeImp *dateProto = new DatePrototypeImp(&globExec, objProto);
   b_DatePrototype = Object(dateProto);
-  RegExpPrototypeImp *regexpProto = new RegExpPrototypeImp(globExec,objProto,funcProto);
+  RegExpPrototypeImp *regexpProto = new RegExpPrototypeImp(&globExec, objProto, funcProto);
   b_RegExpPrototype = Object(regexpProto);
-  ErrorPrototypeImp *errorProto = new ErrorPrototypeImp(globExec,objProto,funcProto);
+  ErrorPrototypeImp *errorProto = new ErrorPrototypeImp(&globExec, objProto, funcProto);
   b_ErrorPrototype = Object(errorProto);
 
   static_cast<ObjectImp*>(global.imp())->setPrototype(b_ObjectPrototype);
 
   // Constructors (Object, Array, etc.)
-  b_Object = Object(new ObjectObjectImp(globExec, objProto, funcProto));
-  b_Function = Object(new FunctionObjectImp(globExec, funcProto));
-  b_Array = Object(new ArrayObjectImp(globExec, funcProto, arrayProto));
-  b_String = Object(new StringObjectImp(globExec, funcProto, stringProto));
-  b_Boolean = Object(new BooleanObjectImp(globExec, funcProto, booleanProto));
-  b_Number = Object(new NumberObjectImp(globExec, funcProto, numberProto));
-  b_Date = Object(new DateObjectImp(globExec, funcProto, dateProto));
-  b_RegExp = Object(new RegExpObjectImp(globExec, funcProto, regexpProto));
-  b_Error = Object(new ErrorObjectImp(globExec, funcProto, errorProto));
+  b_Object = Object(new ObjectObjectImp(&globExec, objProto, funcProto));
+  b_Function = Object(new FunctionObjectImp(&globExec, funcProto));
+  b_Array = Object(new ArrayObjectImp(&globExec, funcProto, arrayProto));
+  b_String = Object(new StringObjectImp(&globExec, funcProto, stringProto));
+  b_Boolean = Object(new BooleanObjectImp(&globExec, funcProto, booleanProto));
+  b_Number = Object(new NumberObjectImp(&globExec, funcProto, numberProto));
+  b_Date = Object(new DateObjectImp(&globExec, funcProto, dateProto));
+  b_RegExp = Object(new RegExpObjectImp(&globExec, funcProto, regexpProto));
+  b_Error = Object(new ErrorObjectImp(&globExec, funcProto, errorProto));
 
   // Error object prototypes
-  b_evalErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
-                                                            "EvalError","EvalError"));
-  b_rangeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
-                                                            "RangeError","RangeError"));
-  b_referenceErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
-                                                            "ReferenceError","ReferenceError"));
-  b_syntaxErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
-                                                            "SyntaxError","SyntaxError"));
-  b_typeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
-                                                            "TypeError","TypeError"));
-  b_uriErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,URIError,
-                                                            "URIError","URIError"));
+  b_evalErrorPrototype = Object(new NativeErrorPrototypeImp(&globExec, errorProto, EvalError,
+                                                            "EvalError", "EvalError"));
+  b_rangeErrorPrototype = Object(new NativeErrorPrototypeImp(&globExec, errorProto, RangeError,
+                                                            "RangeError", "RangeError"));
+  b_referenceErrorPrototype = Object(new NativeErrorPrototypeImp(&globExec, errorProto, ReferenceError,
+                                                            "ReferenceError", "ReferenceError"));
+  b_syntaxErrorPrototype = Object(new NativeErrorPrototypeImp(&globExec, errorProto, SyntaxError,
+                                                            "SyntaxError", "SyntaxError"));
+  b_typeErrorPrototype = Object(new NativeErrorPrototypeImp(&globExec, errorProto, TypeError,
+                                                            "TypeError", "TypeError"));
+  b_uriErrorPrototype = Object(new NativeErrorPrototypeImp(&globExec, errorProto, URIError,
+                                                            "URIError", "URIError"));
 
   // Error objects
-  b_evalError = Object(new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
-  b_rangeError = Object(new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
-  b_referenceError = Object(new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
-  b_syntaxError = Object(new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
-  b_typeError = Object(new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
-  b_uriError = Object(new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
+  b_evalError = Object(new NativeErrorImp(&globExec, funcProto, b_evalErrorPrototype));
+  b_rangeError = Object(new NativeErrorImp(&globExec, funcProto, b_rangeErrorPrototype));
+  b_referenceError = Object(new NativeErrorImp(&globExec, funcProto, b_referenceErrorPrototype));
+  b_syntaxError = Object(new NativeErrorImp(&globExec, funcProto, b_syntaxErrorPrototype));
+  b_typeError = Object(new NativeErrorImp(&globExec, funcProto, b_typeErrorPrototype));
+  b_uriError = Object(new NativeErrorImp(&globExec, funcProto, b_uriErrorPrototype));
 
   // ECMA 15.3.4.1
-  funcProto->put(globExec,"constructor", b_Function, DontEnum);
-
-  global.put(globExec,"Object", b_Object, DontEnum);
-  global.put(globExec,"Function", b_Function, DontEnum);
-  global.put(globExec,"Array", b_Array, DontEnum);
-  global.put(globExec,"Boolean", b_Boolean, DontEnum);
-  global.put(globExec,"String", b_String, DontEnum);
-  global.put(globExec,"Number", b_Number, DontEnum);
-  global.put(globExec,"Date", b_Date, DontEnum);
-  global.put(globExec,"RegExp", b_RegExp, DontEnum);
-  global.put(globExec,"Error", b_Error, DontEnum);
+  funcProto->put(&globExec, "constructor", b_Function, DontEnum);
+
+  global.put(&globExec, "Object", b_Object, DontEnum);
+  global.put(&globExec, "Function", b_Function, DontEnum);
+  global.put(&globExec, "Array", b_Array, DontEnum);
+  global.put(&globExec, "Boolean", b_Boolean, DontEnum);
+  global.put(&globExec, "String", b_String, DontEnum);
+  global.put(&globExec, "Number", b_Number, DontEnum);
+  global.put(&globExec, "Date", b_Date, DontEnum);
+  global.put(&globExec, "RegExp", b_RegExp, DontEnum);
+  global.put(&globExec, "Error", b_Error, DontEnum);
   // Using Internal for those to have something != 0
   // (see kjs_window). Maybe DontEnum would be ok too ?
-  global.put(globExec,"EvalError",b_evalError, Internal);
-  global.put(globExec,"RangeError",b_rangeError, Internal);
-  global.put(globExec,"ReferenceError",b_referenceError, Internal);
-  global.put(globExec,"SyntaxError",b_syntaxError, Internal);
-  global.put(globExec,"TypeError",b_typeError, Internal);
-  global.put(globExec,"URIError",b_uriError, Internal);
+  global.put(&globExec, "EvalError",b_evalError, Internal);
+  global.put(&globExec, "RangeError",b_rangeError, Internal);
+  global.put(&globExec, "ReferenceError",b_referenceError, Internal);
+  global.put(&globExec, "SyntaxError",b_syntaxError, Internal);
+  global.put(&globExec, "TypeError",b_typeError, Internal);
+  global.put(&globExec, "URIError",b_uriError, Internal);
 
   // Set the "constructor" property of all builtin constructors
-  objProto->put(globExec, "constructor", b_Object, DontEnum | DontDelete | ReadOnly);
-  funcProto->put(globExec, "constructor", b_Function, DontEnum | DontDelete | ReadOnly);
-  arrayProto->put(globExec, "constructor", b_Array, DontEnum | DontDelete | ReadOnly);
-  booleanProto->put(globExec, "constructor", b_Boolean, DontEnum | DontDelete | ReadOnly);
-  stringProto->put(globExec, "constructor", b_String, DontEnum | DontDelete | ReadOnly);
-  numberProto->put(globExec, "constructor", b_Number, DontEnum | DontDelete | ReadOnly);
-  dateProto->put(globExec, "constructor", b_Date, DontEnum | DontDelete | ReadOnly);
-  regexpProto->put(globExec, "constructor", b_RegExp, DontEnum | DontDelete | ReadOnly);
-  errorProto->put(globExec, "constructor", b_Error, DontEnum | DontDelete | ReadOnly);
-  b_evalErrorPrototype.put(globExec, "constructor", b_evalError, DontEnum | DontDelete | ReadOnly);
-  b_rangeErrorPrototype.put(globExec, "constructor", b_rangeError, DontEnum | DontDelete | ReadOnly);
-  b_referenceErrorPrototype.put(globExec, "constructor", b_referenceError, DontEnum | DontDelete | ReadOnly);
-  b_syntaxErrorPrototype.put(globExec, "constructor", b_syntaxError, DontEnum | DontDelete | ReadOnly);
-  b_typeErrorPrototype.put(globExec, "constructor", b_typeError, DontEnum | DontDelete | ReadOnly);
-  b_uriErrorPrototype.put(globExec, "constructor", b_uriError, DontEnum | DontDelete | ReadOnly);
+  objProto->put(&globExec, "constructor", b_Object, DontEnum | DontDelete | ReadOnly);
+  funcProto->put(&globExec, "constructor", b_Function, DontEnum | DontDelete | ReadOnly);
+  arrayProto->put(&globExec, "constructor", b_Array, DontEnum | DontDelete | ReadOnly);
+  booleanProto->put(&globExec, "constructor", b_Boolean, DontEnum | DontDelete | ReadOnly);
+  stringProto->put(&globExec, "constructor", b_String, DontEnum | DontDelete | ReadOnly);
+  numberProto->put(&globExec, "constructor", b_Number, DontEnum | DontDelete | ReadOnly);
+  dateProto->put(&globExec, "constructor", b_Date, DontEnum | DontDelete | ReadOnly);
+  regexpProto->put(&globExec, "constructor", b_RegExp, DontEnum | DontDelete | ReadOnly);
+  errorProto->put(&globExec, "constructor", b_Error, DontEnum | DontDelete | ReadOnly);
+  b_evalErrorPrototype.put(&globExec, "constructor", b_evalError, DontEnum | DontDelete | ReadOnly);
+  b_rangeErrorPrototype.put(&globExec, "constructor", b_rangeError, DontEnum | DontDelete | ReadOnly);
+  b_referenceErrorPrototype.put(&globExec, "constructor", b_referenceError, DontEnum | DontDelete | ReadOnly);
+  b_syntaxErrorPrototype.put(&globExec, "constructor", b_syntaxError, DontEnum | DontDelete | ReadOnly);
+  b_typeErrorPrototype.put(&globExec, "constructor", b_typeError, DontEnum | DontDelete | ReadOnly);
+  b_uriErrorPrototype.put(&globExec, "constructor", b_uriError, DontEnum | DontDelete | ReadOnly);
 
   // built-in values
-  global.put(globExec, "NaN",        Number(NaN), DontEnum|DontDelete);
-  global.put(globExec, "Infinity",   Number(Inf), DontEnum|DontDelete);
-  global.put(globExec, "undefined",  Undefined(), DontEnum|DontDelete);
+  global.put(&globExec, "NaN",        Number(NaN), DontEnum|DontDelete);
+  global.put(&globExec, "Infinity",   Number(Inf), DontEnum|DontDelete);
+  global.put(&globExec, "undefined",  Undefined(), DontEnum|DontDelete);
 
   // built-in functions
-  global.put(globExec,"eval",       Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval,       1)), DontEnum);
-  global.put(globExec,"parseInt",   Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt,   2)), DontEnum);
-  global.put(globExec,"parseFloat", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat, 1)), DontEnum);
-  global.put(globExec,"isNaN",      Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN,      1)), DontEnum);
-  global.put(globExec,"isFinite",   Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite,   1)), DontEnum);
-  global.put(globExec,"escape",     Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape,     1)), DontEnum);
-  global.put(globExec,"unescape",   Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape,   1)), DontEnum);
-  global.put(globExec,"decodeURI",  Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURI,  1)), DontEnum);
-  global.put(globExec,"decodeURIComponent", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURIComponent, 1)), DontEnum);
-  global.put(globExec,"encodeURI",  Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURI,  1)), DontEnum);
-  global.put(globExec,"encodeURIComponent", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURIComponent, 1)), DontEnum);
+  global.put(&globExec, "eval",       Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Eval, 1)), DontEnum);
+  global.put(&globExec, "parseInt",   Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseInt, 2)), DontEnum);
+  global.put(&globExec, "parseFloat", Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseFloat, 1)), DontEnum);
+  global.put(&globExec, "isNaN",      Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsNaN, 1)), DontEnum);
+  global.put(&globExec, "isFinite",   Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsFinite, 1)), DontEnum);
+  global.put(&globExec, "escape",     Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Escape, 1)), DontEnum);
+  global.put(&globExec, "unescape",   Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::UnEscape, 1)), DontEnum);
+  global.put(&globExec, "decodeURI",  Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURI, 1)), DontEnum);
+  global.put(&globExec, "decodeURIComponent", Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1)), DontEnum);
+  global.put(&globExec, "encodeURI",  Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURI, 1)), DontEnum);
+  global.put(&globExec, "encodeURIComponent", Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1)), DontEnum);
 #ifndef NDEBUG
-  global.put(globExec,"kjsprint",   Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::KJSPrint,   1)), DontEnum);
+  global.put(&globExec, "kjsprint",   Object(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::KJSPrint, 1)), DontEnum);
 #endif
 
   // built-in objects
-  global.put(globExec,"Math", Object(new MathObjectImp(globExec,objProto)), DontEnum);
+  global.put(&globExec, "Math", Object(new MathObjectImp(&globExec, objProto)), DontEnum);
 }
 
 InterpreterImp::~InterpreterImp()
 {
   if (dbg)
     dbg->detach(m_interpreter);
-  delete globExec;
-  globExec = 0L;
   clear();
 }
 
@@ -745,11 +743,11 @@ Completion InterpreterImp::evaluate(const UString &code, const Value &thisV, con
   // prevent against infinite recursion
   if (recursion >= 20) {
 #if APPLE_CHANGES
-    Completion result = Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
+    Completion result = Completion(Throw, Error::create(&globExec, GeneralError, "Recursion too deep"));
     unlockInterpreter();
     return result;
 #else
-    return Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
+    return Completion(Throw,Error::create(&globExec, GeneralError, "Recursion too deep"));
 #endif
   }
   
@@ -761,7 +759,7 @@ Completion InterpreterImp::evaluate(const UString &code, const Value &thisV, con
 
   // notify debugger that source has been parsed
   if (dbg) {
-    bool cont = dbg->sourceParsed(globExec,sid,sourceURL,code,errLine);
+    bool cont = dbg->sourceParsed(&globExec, sid, sourceURL, code, errLine);
     if (!cont)
 #if APPLE_CHANGES
       {
@@ -775,15 +773,15 @@ Completion InterpreterImp::evaluate(const UString &code, const Value &thisV, con
   
   // no program node means a syntax error occurred
   if (!progNode) {
-    Object err = Error::create(globExec,SyntaxError,errMsg.ascii(),errLine, -1, &sourceURL);
-    err.put(globExec,"sid",Number(sid));
+    Object err = Error::create(&globExec, SyntaxError, errMsg.ascii(), errLine, -1, &sourceURL);
+    err.put(&globExec, "sid", Number(sid));
 #if APPLE_CHANGES
     unlockInterpreter();
 #endif
     return Completion(Throw,err);
   }
 
-  globExec->clearException();
+  globExec.clearException();
 
   recursion++;
   progNode->ref();
@@ -796,15 +794,15 @@ Completion InterpreterImp::evaluate(const UString &code, const Value &thisV, con
     if (thisV.isA(NullType) || thisV.isA(UndefinedType))
       thisObj = globalObject();
     else {
-      thisObj = thisV.toObject(globExec);
+      thisObj = thisV.toObject(&globExec);
     }
   }
 
   Completion res;
-  if (globExec->hadException()) {
+  if (globExec.hadException()) {
     // the thisArg.toObject() conversion above might have thrown an exception - if so,
     // propagate it back
-    res = Completion(Throw,globExec->exception());
+    res = Completion(Throw, globExec.exception());
   }
   else {
     // execute the code
index 582662e..d362267 100644 (file)
@@ -28,6 +28,7 @@
 #include "ustring.h"
 #include "value.h"
 #include "object.h"
+#include "protected_object.h"
 #include "types.h"
 #include "interpreter.h"
 #include "scope_chain.h"
@@ -287,7 +288,7 @@ namespace KJS {
 
     void mark();
 
-    ExecState *globalExec() { return globExec; }
+    ExecState *globalExec() { return &globExec; }
     bool checkSyntax(const UString &code);
     Completion evaluate(const UString &code, const Value &thisV, const UString &sourceURL, int startingLineNumber);
     Debugger *debugger() const { return dbg; }
@@ -387,7 +388,7 @@ namespace KJS {
     ProtectedObject b_typeErrorPrototype;
     ProtectedObject b_uriErrorPrototype;
 
-    ExecState *globExec;
+    ExecState globExec;
     Interpreter::CompatMode m_compatMode;
 
     // Chained list of interpreters (ring) - for collector
index 770c424..3a5fa82 100644 (file)
@@ -26,6 +26,9 @@
 #include "object.h"
 #include "types.h"
 #include "interpreter.h"
+#if APPLE_CHANGES
+#include "runtime.h"
+#endif
 
 #include <assert.h>
 #include <math.h>
@@ -64,12 +67,18 @@ const Context Context::callingContext() const
 
 // ------------------------------ Interpreter ----------------------------------
 
-Interpreter::Interpreter(const Object &global) : rep(0)
+Interpreter::Interpreter(const Object &global) 
+  : rep(0)
+  , m_argumentsPropertyName(&argumentsPropertyName)
+  , m_specialPrototypePropertyName(&specialPrototypePropertyName)
 {
   rep = new InterpreterImp(this,global);
 }
 
 Interpreter::Interpreter()
+  : rep(0)
+  , m_argumentsPropertyName(&argumentsPropertyName)
+  , m_specialPrototypePropertyName(&specialPrototypePropertyName)
 {
   Object global(new ObjectImp());
   rep = new InterpreterImp(this,global);
@@ -328,9 +337,9 @@ void Interpreter::setShouldPrintExceptions(bool print)
 }
 
 
-void *Interpreter::createLanguageInstanceForValue (ExecState *exec, Bindings::Instance::BindingLanguage language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current)
+void *Interpreter::createLanguageInstanceForValue (ExecState *exec, int language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current)
 {
-    return Bindings::Instance::createLanguageInstanceForValue (exec, language, value, origin, current);
+    return Bindings::Instance::createLanguageInstanceForValue (exec, (Bindings::Instance::BindingLanguage)language, value, origin, current);
 }
 
 #endif
index 6199409..1c68bc1 100644 (file)
 #ifndef _KJS_INTERPRETER_H_
 #define _KJS_INTERPRETER_H_
 
+#include "object_wrapper.h"
 #include "value.h"
-#include "object.h"
 #include "types.h"
-#include "protect.h"
-
-#if APPLE_CHANGES
-
-#include "runtime.h"
-
-#endif
 
 namespace KJS {
 
   class ContextImp;
   class InterpreterImp;
+  class RuntimeMethodImp;
+
+  namespace Bindings {
+    class RootObject;
+  }
 
   /**
    * Represents an execution context, as specified by section 10 of the ECMA
@@ -401,12 +399,20 @@ namespace KJS {
      */
     virtual bool isSafeScript (const Interpreter *target) { return true; }
     
-    virtual void *createLanguageInstanceForValue (ExecState *exec, Bindings::Instance::BindingLanguage language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current);
+    virtual void *createLanguageInstanceForValue (ExecState *exec, int language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current);
 #endif
+
+    // This is a workaround to avoid accessing the global variables for these identifiers in
+    // important property lookup functions, to avoid taking PIC branches in Mach-O binaries
+    const Identifier& argumentsIdentifier() { return *m_argumentsPropertyName; }
+    const Identifier& specialPrototypeIdentifier() { return *m_specialPrototypePropertyName; }
     
   private:
     InterpreterImp *rep;
 
+    const Identifier *m_argumentsPropertyName;
+    const Identifier *m_specialPrototypePropertyName;
+
     /**
      * This constructor is not implemented, in order to prevent
      * copy-construction of Interpreter objects. You should always pass around
@@ -420,6 +426,7 @@ namespace KJS {
      * interpreter instance instead.
      */
     Interpreter operator=(const Interpreter&);
+
   protected:
     virtual void virtual_hook( int id, void* data );
   };
@@ -473,7 +480,7 @@ namespace KJS {
         : _interpreter(interp), _context(con) { }
     Interpreter *_interpreter;
     ContextImp *_context;
-    ProtectedValue _exception;
+    Value _exception;
   };
 
 } // namespace
index 4b2cc43..c1aabab 100644 (file)
@@ -124,26 +124,36 @@ namespace KJS {
   class UString;
   /**
    * @internal
-   * Helper for lookupFunction and lookupValueOrFunction
+   * Helper for getStaticFunctionSlot and getStaticPropertySlot
    */
   template <class FuncImp>
-  inline Value lookupOrCreateFunction(ExecState *exec, const Identifier &propertyName,
-                                      const ObjectImp *thisObj, int token, int params, int attr)
+  inline Value staticFunctionGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
   {
       // Look for cached value in dynamic map of properties (in ObjectImp)
-      ValueImp * cachedVal = thisObj->ObjectImp::getDirect(propertyName);
-      /*if (cachedVal)
-        fprintf(stderr, "lookupOrCreateFunction: Function -> looked up in ObjectImp, found type=%d\n", cachedVal->type());*/
+      ObjectImp *thisObj = slot.slotBase();
+      ValueImp *cachedVal = thisObj->getDirect(propertyName);
       if (cachedVal)
-        return Value(cachedVal);
+          return Value(cachedVal);
 
-      Value val = Value(new FuncImp(exec,token, params));
-      ObjectImp *thatObj = const_cast<ObjectImp *>(thisObj);
-      thatObj->ObjectImp::put(exec, propertyName, val, attr);
+      const HashEntry *entry = slot.staticEntry();
+      Value val = Value(new FuncImp(exec, entry->value, entry->params));
+      thisObj->putDirect(propertyName, val.imp(), entry->attr);
       return val;
   }
 
   /**
+   * @internal
+   * Helper for getStaticValueSlot and getStaticPropertySlot
+   */
+  template <class ThisImp>
+  inline Value staticValueGetter(ExecState *exec, const Identifier&, const PropertySlot& slot)
+  {
+      ThisImp *thisObj = static_cast<ThisImp *>(slot.slotBase());
+      const HashEntry *entry = slot.staticEntry();
+      return thisObj->getValueProperty(exec, entry->value);
+  }
+
+  /**
    * Helper method for property lookups
    *
    * This method does it all (looking in the hashtable, checking for function
@@ -164,57 +174,58 @@ namespace KJS {
    * @param thisObj "this"
    */
   template <class FuncImp, class ThisImp, class ParentImp>
-  inline bool lookupGetOwnProperty(ExecState *exec, const Identifier &propertyName,
-                                   const HashTable* table, const ThisImp* thisObj, Value& result)
+  inline bool getStaticPropertySlot(ExecState *exec, const HashTable* table, 
+                                    ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
   {
     const HashEntry* entry = Lookup::findEntry(table, propertyName);
 
     if (!entry) // not found, forward to parent
-      return thisObj->ParentImp::getOwnProperty(exec, propertyName, result);
+      return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
 
     if (entry->attr & Function)
-      result = lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
+      slot.setStaticEntry(thisObj, entry, staticFunctionGetter<FuncImp>);
     else 
-      result = thisObj->getValueProperty(exec, entry->value);
+      slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
 
     return true;
   }
 
   /**
-   * Simplified version of lookupGet in case there are only functions.
-   * Using this instead of lookupGet prevents 'this' from implementing a dummy getValueProperty.
+   * Simplified version of getStaticPropertySlot in case there are only functions.
+   * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing 
+   * a dummy getValueProperty.
    */
   template <class FuncImp, class ParentImp>
-  inline bool lookupGetOwnFunction(ExecState *exec, const Identifier &propertyName,
-                                   const HashTable* table, const ObjectImp* thisObj, Value& result)
+  inline bool getStaticFunctionSlot(ExecState *exec, const HashTable *table, 
+                                    ObjectImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
   {
     const HashEntry* entry = Lookup::findEntry(table, propertyName);
 
     if (!entry) // not found, forward to parent
-      return static_cast<const ParentImp *>(thisObj)->ParentImp::getOwnProperty(exec, propertyName, result);
+      return static_cast<ParentImp *>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
 
     assert(entry->attr & Function);
 
-    result = lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
+    slot.setStaticEntry(thisObj, entry, staticFunctionGetter<FuncImp>);
     return true;
   }
 
   /**
-   * Simplified version of lookupGet in case there are no functions, only "values".
-   * Using this instead of lookupGet removes the need for a FuncImp class.
+   * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
+   * Using this instead of getStaticPropertySlot removes the need for a FuncImp class.
    */
   template <class ThisImp, class ParentImp>
-  inline bool lookupGetOwnValue(ExecState *exec, const Identifier &propertyName,
-                                const HashTable* table, const ThisImp* thisObj, Value& result)
+  inline bool getStaticValueSlot(ExecState *exec, const HashTable* table, 
+                                 ThisImp* thisObj, const Identifier &propertyName, PropertySlot& slot)
   {
     const HashEntry* entry = Lookup::findEntry(table, propertyName);
 
     if (!entry) // not found, forward to parent
-      return thisObj->ParentImp::getOwnProperty(exec, propertyName, result);
+      return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
 
     assert(!(entry->attr & Function));
 
-    result = thisObj->getValueProperty(exec, entry->value);
+    slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
     return true;
   }
 
@@ -295,33 +306,22 @@ namespace KJS {
   public: \
     virtual const ClassInfo *classInfo() const { return &info; } \
     static const ClassInfo info; \
-    bool getOwnProperty(ExecState *exec, const Identifier &propertyName, Value& result) const; \
-    bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const; \
+    bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&); \
   }; \
   const ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 };
 
 #define IMPLEMENT_PROTOTYPE(ClassProto,ClassFunc) \
-    bool ClassProto::getOwnProperty(ExecState *exec, const Identifier &propertyName, Value& result) const \
+    bool ClassProto::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) \
     { \
-      return lookupGetOwnFunction<ClassFunc,ObjectImp>(exec, propertyName, &ClassProto##Table, this, result); \
-    } \
-    bool ClassProto::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const \
-    { /*stupid but we need this to have a common macro for the declaration*/ \
-      return ObjectImp::hasOwnProperty(exec, propertyName); \
+      return getStaticFunctionSlot<ClassFunc,ObjectImp>(exec, &ClassProto##Table, this, propertyName, slot); \
     }
 
 #define IMPLEMENT_PROTOTYPE_WITH_PARENT(ClassProto,ClassFunc,ParentProto)  \
-    bool ClassProto::getOwnProperty(ExecState *exec, const Identifier &propertyName, Value& result) const \
+    bool ClassProto::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) \
     { \
-      if (lookupGetOwnFunction<ClassFunc,ObjectImp>(exec, propertyName, &ClassProto##Table, this, result)) \
+      if (getStaticFunctionSlot<ClassFunc,ObjectImp>(exec, &ClassProto##Table, this, propertyName, slot)) \
           return true; \
-      return ParentProto::self(exec)->getOwnProperty(exec, propertyName, result); \
-    } \
-    bool ClassProto::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const \
-    { \
-      if (ObjectImp::hasOwnProperty(exec, propertyName)) \
-        return true; \
-      return ParentProto::self(exec)->hasOwnProperty(exec, propertyName); \
+      return ParentProto::self(exec)->getOwnPropertySlot(exec, propertyName, slot); \
     }
 
 #define IMPLEMENT_PROTOFUNC(ClassFunc) \
index 9c18119..6f457aa 100644 (file)
@@ -81,9 +81,9 @@ MathObjectImp::MathObjectImp(ExecState * /*exec*/,
 
 // ECMA 15.8
 
-bool MathObjectImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool MathObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
 {
-  return lookupGetOwnProperty<MathFuncImp, MathObjectImp, ObjectImp>(exec, propertyName, &mathTable, this, result);
+  return getStaticPropertySlot<MathFuncImp, MathObjectImp, ObjectImp>(exec, &mathTable, this, propertyName, slot);
 }
 
 Value MathObjectImp::getValueProperty(ExecState *, int token) const
index 92eef64..6a92565 100644 (file)
@@ -31,7 +31,7 @@ namespace KJS {
   public:
     MathObjectImp(ExecState *exec,
                   ObjectPrototypeImp *objProto);
-    bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
index b424847..ce83f3a 100644 (file)
@@ -277,42 +277,35 @@ Value ResolveNode::evaluate(ExecState *exec)
 {
   ScopeChain chain = exec->context().imp()->scopeChain();
 
-  Value result;
-  while (!chain.isEmpty()) {
-    ObjectImp *o = chain.top();
+  assert(!chain.isEmpty());
 
-    if (o->getProperty(exec, ident, result))
-      return result;
+  PropertySlot slot;
+  do { 
+    ObjectImp *o = chain.top();
+    if (o->getPropertySlot(exec, ident, slot))
+      return slot.getValue(exec, ident);
     
     chain.pop();
-  }
+  } while (!chain.isEmpty());
 
-  UString m = I18N_NOOP("Can't find variable: ") + ident.ustring();
-  Object err = Error::create(exec, ReferenceError, m.ascii());
-  exec->setException(err);
-  return err;
+  return Reference(Null(), ident).getValue(exec);
 }
 
 Reference ResolveNode::evaluateReference(ExecState *exec)
 {
   ScopeChain chain = exec->context().imp()->scopeChain();
 
-  while (!chain.isEmpty()) {
-    ObjectImp *o = chain.top();
+  assert(!chain.isEmpty());
 
-    //cout << "Resolve: looking at '" << ident.ascii() << "'"
-    //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
-    if (o->hasProperty(exec,ident)) {
-      //cout << "Resolve: FOUND '" << ident.ascii() << "'"
-      //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
+  PropertySlot slot;
+  do { 
+    ObjectImp *o = chain.top();
+    if (o->getPropertySlot(exec, ident, slot))
       return Reference(o, ident);
-    }
     
     chain.pop();
-  }
+  } while (!chain.isEmpty());
 
-  // identifier not found
-  //cout << "Resolve: didn't find '" << ident.ascii() << "'" << endl;
   return Reference(Null(), ident);
 }
 
@@ -529,7 +522,17 @@ bool AccessorNode1::deref()
 // ECMA 11.2.1a
 Value AccessorNode1::evaluate(ExecState *exec)
 {
-  return evaluateReference(exec).getValue(exec);
+  Value v1 = expr1->evaluate(exec);
+  KJS_CHECKEXCEPTIONVALUE
+  Value v2 = expr2->evaluate(exec);
+  KJS_CHECKEXCEPTIONVALUE
+  Object o = v1.toObject(exec);
+  unsigned i;
+  if (v2.toUInt32(i))
+    return o.get(exec, i);
+
+  String s = v2.toString(exec);
+  return o.get(exec, Identifier(s.value()));
 }
 
 Reference AccessorNode1::evaluateReference(ExecState *exec)
@@ -566,7 +569,11 @@ bool AccessorNode2::deref()
 // ECMA 11.2.1b
 Value AccessorNode2::evaluate(ExecState *exec)
 {
-  return evaluateReference(exec).getValue(exec);
+  Value v = expr->evaluate(exec);
+  KJS_CHECKEXCEPTIONVALUE
+  Object o = v.toObject(exec);
+  return o.get(exec, ident);
+
 }
 
 Reference AccessorNode2::evaluateReference(ExecState *exec)
index 3fe0954..a26fb46 100644 (file)
@@ -402,9 +402,9 @@ NumberObjectImp::NumberObjectImp(ExecState *exec,
   putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
 }
 
-bool NumberObjectImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool NumberObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<NumberObjectImp, InternalFunctionImp>(exec, propertyName, &numberTable, this, result);
+  return getStaticValueSlot<NumberObjectImp, InternalFunctionImp>(exec, &numberTable, this, propertyName, slot);
 }
 
 Value NumberObjectImp::getValueProperty(ExecState *, int token) const
index dddbb1d..db8c64e 100644 (file)
@@ -84,7 +84,7 @@ namespace KJS {
     virtual bool implementsCall() const;
     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
 
-    bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
index 1c5532e..dad26f4 100644 (file)
@@ -208,67 +208,68 @@ UString ObjectImp::className() const
 
 Value ObjectImp::get(ExecState *exec, const Identifier &propertyName) const
 {
-  Value result;
-
-  const ObjectImp *imp = this;
-
-  while (true) {
-    if (imp->getOwnProperty(exec, propertyName, result))
-      return result;
-
-    const ValueImp *proto = imp->_proto;
-    if (proto->dispatchType() != ObjectType)
-      break;
-
-    imp = static_cast<const ObjectImp *>(proto);
-  }
+  PropertySlot slot;
 
+  if (const_cast<ObjectImp *>(this)->getPropertySlot(exec, propertyName, slot))
+    return slot.getValue(exec, propertyName);
+    
   return Undefined();
 }
 
-bool ObjectImp::getOwnProperty(ExecState *exec, unsigned propertyName, Value& result) const
+Value ObjectImp::get(ExecState *exec, unsigned propertyName) const
 {
-  return getOwnProperty(exec, Identifier::from(propertyName), result);
+  PropertySlot slot;
+  if (const_cast<ObjectImp *>(this)->getPropertySlot(exec, propertyName, slot))
+    return slot.getValue(exec, propertyName);
+    
+  return Undefined();
 }
 
-Value ObjectImp::get(ExecState *exec, unsigned propertyName) const
+bool ObjectImp::getProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
 {
-  Value result;
-
-  const ObjectImp *imp = this;
-
-  while (imp) {
-    if (imp->getOwnProperty(exec, propertyName, result))
-      return result;
-
-    const ValueImp *proto = imp->_proto;
-    if (proto->dispatchType() != ObjectType)
-      break;
-
-    imp = static_cast<const ObjectImp *>(proto);
+  PropertySlot slot;
+  if (const_cast<ObjectImp *>(this)->getPropertySlot(exec, propertyName, slot)) {
+    result = slot.getValue(exec, propertyName);
+    return true;
   }
-
-  return Undefined();
+  
+  return false;
 }
 
 bool ObjectImp::getProperty(ExecState *exec, unsigned propertyName, Value& result) const
 {
-  const ObjectImp *imp = this;
+  PropertySlot slot;
+  if (const_cast<ObjectImp *>(this)->getPropertySlot(exec, propertyName, slot)) {
+    result = slot.getValue(exec, propertyName);
+    return true;
+  }
+    
+  return false;
+}
+
+bool ObjectImp::getPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
+{
+  ObjectImp *imp = this;
   
   while (true) {
-    if (imp->getOwnProperty(exec, propertyName, result))
+    if (imp->getOwnPropertySlot(exec, propertyName, slot))
       return true;
     
-    const ValueImp *proto = imp->_proto;
-      if (proto->dispatchType() != ObjectType)
-        break;
-      
-      imp = static_cast<const ObjectImp *>(proto);
+    ValueImp *proto = imp->_proto;
+    if (proto->dispatchType() != ObjectType)
+      break;
+    
+    imp = static_cast<ObjectImp *>(proto);
   }
   
   return false;
 }
 
+bool ObjectImp::getOwnPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
+{
+  return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
+}
+
 // ECMA 8.6.2.2
 void ObjectImp::put(ExecState *exec, const Identifier &propertyName,
                      const Value &value, int attr)
@@ -276,7 +277,7 @@ void ObjectImp::put(ExecState *exec, const Identifier &propertyName,
   assert(!value.isNull());
 
   // non-standard netscape extension
-  if (propertyName == specialPrototypePropertyName) {
+  if (propertyName == exec->dynamicInterpreter()->specialPrototypeIdentifier()) {
     setPrototype(value);
     return;
   }
@@ -323,52 +324,22 @@ bool ObjectImp::canPut(ExecState *, const Identifier &propertyName) const
 // ECMA 8.6.2.4
 bool ObjectImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
 {
-  if (hasOwnProperty(exec, propertyName))
-    return true;
-
-  if (!_proto || _proto->dispatchType() != ObjectType) {
-    return false;
-  }
-
-  // Look in the prototype
-  return static_cast<ObjectImp *>(_proto)->hasProperty(exec, propertyName);
+  PropertySlot slot;
+  return const_cast<ObjectImp *>(this)->getPropertySlot(exec, propertyName, slot);
 }
 
 bool ObjectImp::hasProperty(ExecState *exec, unsigned propertyName) const
 {
-    if (hasOwnProperty(exec, propertyName))
-      return true;
-
-    if (!_proto || _proto->dispatchType() != ObjectType) {
-      return false;
-    }
-
-    // Look in the prototype
-    return static_cast<ObjectImp *>(_proto)->hasProperty(exec, propertyName);
+  PropertySlot slot;
+  return const_cast<ObjectImp *>(this)->getPropertySlot(exec, propertyName, slot);
 }
 
 bool ObjectImp::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
 {
-  if (_prop.get(propertyName))
-    return true;
-
-  // Look in the static hashtable of properties
-  if (findPropertyHashEntry(propertyName))
-    return true;
-
-  // non-standard netscape extension
-  if (propertyName == specialPrototypePropertyName)
-    return true;
-
-  return false;
+  PropertySlot slot;
+  return const_cast<ObjectImp *>(this)->getOwnPropertySlot(exec, propertyName, slot);
 }
 
-bool ObjectImp::hasOwnProperty(ExecState *exec, unsigned propertyName) const
-{
-  return hasOwnProperty(exec, Identifier::from(propertyName));
-}
-
-
 // ECMA 8.6.2.5
 bool ObjectImp::deleteProperty(ExecState */*exec*/, const Identifier &propertyName)
 {
index 596ecea..b43e284 100644 (file)
 #define KJS_MAX_STACK 1000
 #endif
 
-#include "value.h"
 #include "types.h"
+#include "interpreter.h"
 #include "reference_list.h"
 #include "property_map.h"
+#include "property_slot.h"
 #include "scope_chain.h"
 
 namespace KJS {
@@ -49,16 +50,6 @@ namespace KJS {
   class HashTable;
   class HashEntry;
   class ListImp;
-  class ReferenceList;
-
-  // ECMA 262-3 8.6.1
-  // Attributes (only applicable to the Object type)
-  enum Attribute { None       = 0,
-                   ReadOnly   = 1 << 1, // property can be only read, not written
-                   DontEnum   = 1 << 2, // property doesn't appear in (for .. in ..)
-                   DontDelete = 1 << 3, // property can't be deleted
-                   Internal   = 1 << 4, // an internal property, set to by pass checks
-                   Function   = 1 << 5 }; // property is a function - only used by static hashtables
 
   /**
    * Class Information
@@ -83,303 +74,6 @@ namespace KJS {
     void *dummy;
   };
   
-  /**
-   * Represents an Object. This is a wrapper for ObjectImp
-   */
-  class Object : public Value {
-  public:
-    Object() { }
-    Object(ObjectImp *);
-    operator ObjectImp *() const { return imp(); }
-    
-    ObjectImp *imp() const;
-
-    const ClassInfo *classInfo() const;
-    bool inherits(const ClassInfo *cinfo) const;
-
-    /**
-     * Converts a Value into an Object. If the value's type is not ObjectType,
-     * a null object will be returned (i.e. one with it's internal pointer set
-     * to 0). If you do not know for sure whether the value is of type
-     * ObjectType, you should check the isValid() methods afterwards before
-     * calling any methods on the Object.
-     *
-     * @return The value converted to an object
-     */
-    static Object dynamicCast(const Value &v);
-
-    /**
-     * Returns the prototype of this object. Note that this is not the same as
-     * the "prototype" property.
-     *
-     * See ECMA 8.6.2
-     *
-     * @return The object's prototype
-     */
-    Value prototype() const;
-
-    /**
-     * Returns the class name of the object
-     *
-     * See ECMA 8.6.2
-     *
-     * @return The object's class name
-     */
-    UString className() const;
-
-    /**
-     * Retrieves the specified property from the object. If neither the object
-     * or any other object in it's prototype chain have the property, this
-     * function will return Undefined.
-     *
-     * See ECMA 8.6.2.1
-     *
-     * @param exec The current execution state
-     * @param propertyName The name of the property to retrieve
-     *
-     * @return The specified property, or Undefined
-     */
-    Value get(ExecState *exec, const Identifier &propertyName) const;
-    Value get(ExecState *exec, unsigned propertyName) const;
-
-    /**
-     * Sets the specified property.
-     *
-     * See ECMA 8.6.2.2
-     *
-     * @param exec The current execution state
-     * @param propertyName The name of the property to set
-     * @param propertyValue The value to set
-     */
-    void put(ExecState *exec, const Identifier &propertyName,
-             const Value &value, int attr = None);
-    void put(ExecState *exec, unsigned propertyName,
-             const Value &value, int attr = None);
-
-    /**
-     * Used to check whether or not a particular property is allowed to be set
-     * on an object
-     *
-     * See ECMA 8.6.2.3
-     *
-     * @param exec The current execution state
-     * @param propertyName The name of the property
-     * @return true if the property can be set, otherwise false
-     */
-    bool canPut(ExecState *exec, const Identifier &propertyName) const;
-
-    /**
-     * Checks to see whether the object (or any object in it's prototype chain)
-     * has a property with the specified name.
-     *
-     * See ECMA 8.6.2.4
-     *
-     * @param exec The current execution state
-     * @param propertyName The name of the property to check for
-     * @return true if the object has the property, otherwise false
-     */
-    bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
-    bool hasProperty(ExecState *exec, unsigned propertyName) const;
-
-    /**
-     * Checks to see whether the object has a property with the specified name.
-     *
-     * See ECMA 15.2.4.5
-     *
-     * @param exec The current execution state
-     * @param propertyName The name of the property to check for
-     * @return true if the object has the property, otherwise false
-     */
-    bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
-    bool hasOwnProperty(ExecState *exec, unsigned propertyName) const;
-
-    /**
-     * Removes the specified property from the object.
-     *
-     * See ECMA 8.6.2.5
-     *
-     * @param exec The current execution state
-     * @param propertyName The name of the property to delete
-     * @return true if the property was successfully deleted or did not
-     * exist on the object. false if deleting the specified property is not
-     * allowed.
-     */
-    bool deleteProperty(ExecState *exec, const Identifier &propertyName);
-    bool deleteProperty(ExecState *exec, unsigned propertyName);
-
-    /**
-     * Converts the object into a primitive value. The value return may differ
-     * depending on the supplied hint
-     *
-     * See ECMA 8.6.2.6
-     *
-     * @param exec The current execution state
-     * @param hint The desired primitive type to convert to
-     * @return A primitive value converted from the objetc. Note that the
-     * type of primitive value returned may not be the same as the requested
-     * hint.
-     */
-    Value defaultValue(ExecState *exec, Type hint) const;
-
-    /**
-     * Whether or not the object implements the construct() method. If this
-     * returns false you should not call the construct() method on this
-     * object (typically, an assertion will fail to indicate this).
-     *
-     * @return true if this object implements the construct() method, otherwise
-     * false
-     */
-    bool implementsConstruct() const;
-
-    /**
-     * Creates a new object based on this object. Typically this means the
-     * following:
-     * 1. A new object is created
-     * 2. The prototype of the new object is set to the value of this object's
-     *    "prototype" property
-     * 3. The call() method of this object is called, with the new object
-     *    passed as the this value
-     * 4. The new object is returned
-     *
-     * In some cases, Host objects may differ from these semantics, although
-     * this is discouraged.
-     *
-     * If an error occurs during construction, the execution state's exception
-     * will be set. This can be tested for with ExecState::hadException().
-     * Under some circumstances, the exception object may also be returned.
-     *
-     * Note: This function should not be called if implementsConstruct() returns
-     * false, in which case it will result in an assertion failure.
-     *
-     * @param exec The current execution state
-     * @param args The arguments to be passed to call() once the new object has
-     * been created
-     * @return The newly created &amp; initialized object
-     */
-    Object construct(ExecState *exec, const List &args);
-    Object construct(ExecState *exec, const List &args, const UString &sourceURL, int lineNumber);
-
-    /**
-     * Whether or not the object implements the call() method. If this returns
-     * false you should not call the call() method on this object (typically,
-     * an assertion will fail to indicate this).
-     *
-     * @return true if this object implements the call() method, otherwise
-     * false
-     */
-    bool implementsCall() const;
-
-
-    /**
-     * Calls this object as if it is a function.
-     *
-     * Note: This function should not be called if implementsCall() returns
-     * false, in which case it will result in an assertion failure.
-     *
-     * See ECMA 8.6.2.3
-     *
-     * @param exec The current execution state
-     * @param thisObj The obj to be used as "this" within function execution.
-     * Note that in most cases this will be different from the C++ "this"
-     * object. For example, if the ECMAScript code "window.location.toString()"
-     * is executed, call() will be invoked on the C++ object which implements
-     * the toString method, with the thisObj being window.location
-     * @param args List of arguments to be passed to the function
-     * @return The return value from the function
-     */
-    Value call(ExecState *exec, Object &thisObj, const List &args);
-
-    /**
-     * Whether or not the object implements the hasInstance() method. If this
-     * returns false you should not call the hasInstance() method on this
-     * object (typically, an assertion will fail to indicate this).
-     *
-     * @return true if this object implements the hasInstance() method,
-     * otherwise false
-     */
-    bool implementsHasInstance() const;
-
-    /**
-     * Checks whether value delegates behavior to this object. Used by the
-     * instanceof operator.
-     *
-     * @param exec The current execution state
-     * @param value The value to check
-     * @return true if value delegates behavior to this object, otherwise
-     * false
-     */
-    Boolean hasInstance(ExecState *exec, const Value &value);
-
-    /**
-     * Returns the scope of this object. This is used when execution declared
-     * functions - the execution context for the function is initialized with
-     * extra object in it's scope. An example of this is functions declared
-     * inside other functions:
-     *
-     * \code
-     * function f() {
-     *
-     *   function b() {
-     *     return prototype;
-     *   }
-     *
-     *   var x = 4;
-     *   // do some stuff
-     * }
-     * f.prototype = new String();
-     * \endcode
-     *
-     * When the function f.b is executed, its scope will include properties of
-     * f. So in the example above the return value of f.b() would be the new
-     * String object that was assigned to f.prototype.
-     *
-     * @param exec The current execution state
-     * @return The function's scope
-     */
-    const ScopeChain &scope() const;
-    void setScope(const ScopeChain &s);
-
-    /**
-     * Returns a List of References to all the properties of the object. Used
-     * in "for x in y" statements. The list is created new, so it can be freely
-     * modified without affecting the object's properties. It should be deleted
-     * by the caller.
-     *
-     * Subclasses can override this method in ObjectImpl to provide the
-     * appearance of
-     * having extra properties other than those set specifically with put().
-     *
-     * @param exec The current execution state
-     * @param recursive Whether or not properties in the object's prototype
-     * chain should be
-     * included in the list.
-     * @return A List of References to properties of the object.
-     **/
-    ReferenceList propList(ExecState *exec, bool recursive = true);
-
-    /**
-     * Returns the internal value of the object. This is used for objects such
-     * as String and Boolean which are wrappers for native types. The interal
-     * value is the actual value represented by the wrapper objects.
-     *
-     * @see ECMA 8.6.2
-     * @return The internal value of the object
-     */
-    Value internalValue() const;
-
-    /**
-     * Sets the internal value of the object
-     *
-     * @see internalValue()
-     *
-     * @param v The new internal value
-     */
-    void setInternalValue(const Value &v);
-
-    void saveProperties(SavedProperties &p) const;
-    void restoreProperties(const SavedProperties &p);
-  };
-
   inline Object Value::toObject(ExecState *exec) const { return rep->dispatchToObject(exec); }
   
   class ObjectImp : public ValueImp {
@@ -509,8 +203,10 @@ namespace KJS {
     bool getProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
     bool getProperty(ExecState *exec, unsigned propertyName, Value& result) const;
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
-    virtual bool getOwnProperty(ExecState *exec, unsigned propertyName, Value& result) const;
+    bool getPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    bool getPropertySlot(ExecState *, unsigned, PropertySlot&);
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    virtual bool getOwnPropertySlot(ExecState *, unsigned index, PropertySlot&);
 
     /**
      * Implementation of the [[Put]] internal property (implemented by all
@@ -537,13 +233,10 @@ namespace KJS {
      *
      * @see Object::hasProperty()
      */
-    bool hasProperty(ExecState *exec,
-                            const Identifier &propertyName) const;
+    bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
     bool hasProperty(ExecState *exec, unsigned propertyName) const;
 
-    virtual bool hasOwnProperty(ExecState *exec,
-                    const Identifier &propertyName) const;
-    virtual bool hasOwnProperty(ExecState *exec, unsigned propertyName) const;
+    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
 
     /**
      * Implementation of the [[Delete]] internal property (implemented by all
@@ -623,6 +316,8 @@ namespace KJS {
     // to look up in the prototype, it might already exist there)
     ValueImp *getDirect(const Identifier& propertyName) const
         { return _prop.get(propertyName); }
+    ValueImp **getDirectLocation(const Identifier& propertyName)
+        { return _prop.getLocation(propertyName); }
     void putDirect(const Identifier &propertyName, ValueImp *value, int attr = 0);
     void putDirect(const Identifier &propertyName, int value, int attr = 0);
     
@@ -638,22 +333,21 @@ namespace KJS {
     ScopeChain _scope;
   };
 
-
   // it may seem crazy to inline a function this large but it makes a big difference
   // since this is function very hot in variable lookup
-  inline bool ObjectImp::getProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+  inline bool ObjectImp::getPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
   {
-    const ObjectImp *imp = this;
+    ObjectImp *imp = this;
 
     while (true) {
-      if (imp->getOwnProperty(exec, propertyName, result))
+      if (imp->getOwnPropertySlot(exec, propertyName, slot))
         return true;
       
-      const ValueImp *proto = imp->_proto;
+      ValueImp *proto = imp->_proto;
       if (proto->dispatchType() != ObjectType)
         break;
       
-      imp = static_cast<const ObjectImp *>(proto);
+      imp = static_cast<ObjectImp *>(proto);
     }
     
     return false;
@@ -662,17 +356,17 @@ namespace KJS {
   // it may seem crazy to inline a function this large, especially a virtual function,
   // but it makes a big difference to property lookup if subclasses can inline their
   // superclass call to this
-  inline bool ObjectImp::getOwnProperty(ExecState *exec, const Identifier &propertyName, Value &result) const
+  inline bool ObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
   {
-      ValueImp *imp = getDirect(propertyName);
-      if (imp) {
-        result = Value(imp);
+      ValueImp **impLocation = getDirectLocation(propertyName);
+      if (impLocation) {
+        slot.setValueSlot(this, impLocation);
         return true;
       }
 
       // non-standard netscape extension
-      if (propertyName == specialPrototypePropertyName) {
-        result = Value(_proto);
+      if (propertyName == exec->dynamicInterpreter()->specialPrototypeIdentifier()) {
+        slot.setValueSlot(this, &_proto);
         return true;
       }
 
@@ -759,15 +453,9 @@ namespace KJS {
   inline bool Object::hasProperty(ExecState *exec, const Identifier &propertyName) const
     { return imp()->hasProperty(exec, propertyName); }
 
-  inline bool Object::hasProperty(ExecState *exec, unsigned propertyName) const
-    { return imp()->hasProperty(exec, propertyName); }
-
   inline bool Object::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
     { return imp()->hasOwnProperty(exec, propertyName); }
 
-  inline bool Object::hasOwnProperty(ExecState *exec, unsigned propertyName) const
-    { return imp()->hasOwnProperty(exec, propertyName); }
-
   inline bool Object::deleteProperty(ExecState *exec, const Identifier &propertyName)
     { return imp()->deleteProperty(exec,propertyName); }
 
diff --git a/JavaScriptCore/kjs/object_wrapper.h b/JavaScriptCore/kjs/object_wrapper.h
new file mode 100644 (file)
index 0000000..6030f13
--- /dev/null
@@ -0,0 +1,321 @@
+
+#ifndef _KJS_OBJECT_WRAPPER_H_
+#define _KJS_OBJECT_WRAPPER_H_
+
+#include "value.h"
+#include "reference_list.h"
+
+namespace KJS {
+
+  class ClassInfo;
+  class ObjectImp;
+  class ScopeChain;
+  class SavedProperties;
+
+  // ECMA 262-3 8.6.1
+  // Attributes (only applicable to the Object type)
+  enum Attribute { None       = 0,
+                   ReadOnly   = 1 << 1, // property can be only read, not written
+                   DontEnum   = 1 << 2, // property doesn't appear in (for .. in ..)
+                   DontDelete = 1 << 3, // property can't be deleted
+                   Internal   = 1 << 4, // an internal property, set to by pass checks
+                   Function   = 1 << 5 }; // property is a function - only used by static hashtables
+
+  /**
+   * Represents an Object. This is a wrapper for ObjectImp
+   */
+  class Object : public Value {
+  public:
+    Object() { }
+    Object(ObjectImp *);
+    operator ObjectImp *() const { return imp(); }
+    
+    ObjectImp *imp() const;
+
+    const ClassInfo *classInfo() const;
+    bool inherits(const ClassInfo *cinfo) const;
+
+    /**
+     * Converts a Value into an Object. If the value's type is not ObjectType,
+     * a null object will be returned (i.e. one with it's internal pointer set
+     * to 0). If you do not know for sure whether the value is of type
+     * ObjectType, you should check the isValid() methods afterwards before
+     * calling any methods on the Object.
+     *
+     * @return The value converted to an object
+     */
+    static Object dynamicCast(const Value &v);
+
+    /**
+     * Returns the prototype of this object. Note that this is not the same as
+     * the "prototype" property.
+     *
+     * See ECMA 8.6.2
+     *
+     * @return The object's prototype
+     */
+    Value prototype() const;
+
+    /**
+     * Returns the class name of the object
+     *
+     * See ECMA 8.6.2
+     *
+     * @return The object's class name
+     */
+    UString className() const;
+
+    /**
+     * Retrieves the specified property from the object. If neither the object
+     * or any other object in it's prototype chain have the property, this
+     * function will return Undefined.
+     *
+     * See ECMA 8.6.2.1
+     *
+     * @param exec The current execution state
+     * @param propertyName The name of the property to retrieve
+     *
+     * @return The specified property, or Undefined
+     */
+    Value get(ExecState *exec, const Identifier &propertyName) const;
+    Value get(ExecState *exec, unsigned propertyName) const;
+
+    /**
+     * Sets the specified property.
+     *
+     * See ECMA 8.6.2.2
+     *
+     * @param exec The current execution state
+     * @param propertyName The name of the property to set
+     * @param propertyValue The value to set
+     */
+    void put(ExecState *exec, const Identifier &propertyName,
+             const Value &value, int attr = None);
+    void put(ExecState *exec, unsigned propertyName,
+             const Value &value, int attr = None);
+
+    /**
+     * Used to check whether or not a particular property is allowed to be set
+     * on an object
+     *
+     * See ECMA 8.6.2.3
+     *
+     * @param exec The current execution state
+     * @param propertyName The name of the property
+     * @return true if the property can be set, otherwise false
+     */
+    bool canPut(ExecState *exec, const Identifier &propertyName) const;
+
+    /**
+     * Checks to see whether the object (or any object in it's prototype chain)
+     * has a property with the specified name.
+     *
+     * See ECMA 8.6.2.4
+     *
+     * @param exec The current execution state
+     * @param propertyName The name of the property to check for
+     * @return true if the object has the property, otherwise false
+     */
+    bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
+
+    /**
+     * Checks to see whether the object has a property with the specified name.
+     *
+     * See ECMA 15.2.4.5
+     *
+     * @param exec The current execution state
+     * @param propertyName The name of the property to check for
+     * @return true if the object has the property, otherwise false
+     */
+    bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
+
+    /**
+     * Removes the specified property from the object.
+     *
+     * See ECMA 8.6.2.5
+     *
+     * @param exec The current execution state
+     * @param propertyName The name of the property to delete
+     * @return true if the property was successfully deleted or did not
+     * exist on the object. false if deleting the specified property is not
+     * allowed.
+     */
+    bool deleteProperty(ExecState *exec, const Identifier &propertyName);
+    bool deleteProperty(ExecState *exec, unsigned propertyName);
+
+    /**
+     * Converts the object into a primitive value. The value return may differ
+     * depending on the supplied hint
+     *
+     * See ECMA 8.6.2.6
+     *
+     * @param exec The current execution state
+     * @param hint The desired primitive type to convert to
+     * @return A primitive value converted from the objetc. Note that the
+     * type of primitive value returned may not be the same as the requested
+     * hint.
+     */
+    Value defaultValue(ExecState *exec, Type hint) const;
+
+    /**
+     * Whether or not the object implements the construct() method. If this
+     * returns false you should not call the construct() method on this
+     * object (typically, an assertion will fail to indicate this).
+     *
+     * @return true if this object implements the construct() method, otherwise
+     * false
+     */
+    bool implementsConstruct() const;
+
+    /**
+     * Creates a new object based on this object. Typically this means the
+     * following:
+     * 1. A new object is created
+     * 2. The prototype of the new object is set to the value of this object's
+     *    "prototype" property
+     * 3. The call() method of this object is called, with the new object
+     *    passed as the this value
+     * 4. The new object is returned
+     *
+     * In some cases, Host objects may differ from these semantics, although
+     * this is discouraged.
+     *
+     * If an error occurs during construction, the execution state's exception
+     * will be set. This can be tested for with ExecState::hadException().
+     * Under some circumstances, the exception object may also be returned.
+     *
+     * Note: This function should not be called if implementsConstruct() returns
+     * false, in which case it will result in an assertion failure.
+     *
+     * @param exec The current execution state
+     * @param args The arguments to be passed to call() once the new object has
+     * been created
+     * @return The newly created &amp; initialized object
+     */
+    Object construct(ExecState *exec, const List &args);
+    Object construct(ExecState *exec, const List &args, const UString &sourceURL, int lineNumber);
+
+    /**
+     * Whether or not the object implements the call() method. If this returns
+     * false you should not call the call() method on this object (typically,
+     * an assertion will fail to indicate this).
+     *
+     * @return true if this object implements the call() method, otherwise
+     * false
+     */
+    bool implementsCall() const;
+
+
+    /**
+     * Calls this object as if it is a function.
+     *
+     * Note: This function should not be called if implementsCall() returns
+     * false, in which case it will result in an assertion failure.
+     *
+     * See ECMA 8.6.2.3
+     *
+     * @param exec The current execution state
+     * @param thisObj The obj to be used as "this" within function execution.
+     * Note that in most cases this will be different from the C++ "this"
+     * object. For example, if the ECMAScript code "window.location.toString()"
+     * is executed, call() will be invoked on the C++ object which implements
+     * the toString method, with the thisObj being window.location
+     * @param args List of arguments to be passed to the function
+     * @return The return value from the function
+     */
+    Value call(ExecState *exec, Object &thisObj, const List &args);
+
+    /**
+     * Whether or not the object implements the hasInstance() method. If this
+     * returns false you should not call the hasInstance() method on this
+     * object (typically, an assertion will fail to indicate this).
+     *
+     * @return true if this object implements the hasInstance() method,
+     * otherwise false
+     */
+    bool implementsHasInstance() const;
+
+    /**
+     * Checks whether value delegates behavior to this object. Used by the
+     * instanceof operator.
+     *
+     * @param exec The current execution state
+     * @param value The value to check
+     * @return true if value delegates behavior to this object, otherwise
+     * false
+     */
+    Boolean hasInstance(ExecState *exec, const Value &value);
+
+    /**
+     * Returns the scope of this object. This is used when execution declared
+     * functions - the execution context for the function is initialized with
+     * extra object in it's scope. An example of this is functions declared
+     * inside other functions:
+     *
+     * \code
+     * function f() {
+     *
+     *   function b() {
+     *     return prototype;
+     *   }
+     *
+     *   var x = 4;
+     *   // do some stuff
+     * }
+     * f.prototype = new String();
+     * \endcode
+     *
+     * When the function f.b is executed, its scope will include properties of
+     * f. So in the example above the return value of f.b() would be the new
+     * String object that was assigned to f.prototype.
+     *
+     * @param exec The current execution state
+     * @return The function's scope
+     */
+    const ScopeChain &scope() const;
+    void setScope(const ScopeChain &s);
+
+    /**
+     * Returns a List of References to all the properties of the object. Used
+     * in "for x in y" statements. The list is created new, so it can be freely
+     * modified without affecting the object's properties. It should be deleted
+     * by the caller.
+     *
+     * Subclasses can override this method in ObjectImpl to provide the
+     * appearance of
+     * having extra properties other than those set specifically with put().
+     *
+     * @param exec The current execution state
+     * @param recursive Whether or not properties in the object's prototype
+     * chain should be
+     * included in the list.
+     * @return A List of References to properties of the object.
+     **/
+    ReferenceList propList(ExecState *exec, bool recursive = true);
+
+    /**
+     * Returns the internal value of the object. This is used for objects such
+     * as String and Boolean which are wrappers for native types. The interal
+     * value is the actual value represented by the wrapper objects.
+     *
+     * @see ECMA 8.6.2
+     * @return The internal value of the object
+     */
+    Value internalValue() const;
+
+    /**
+     * Sets the internal value of the object
+     *
+     * @see internalValue()
+     *
+     * @param v The new internal value
+     */
+    void setInternalValue(const Value &v);
+
+    void saveProperties(SavedProperties &p) const;
+    void restoreProperties(const SavedProperties &p);
+  };
+
+} // namespace
+
+#endif // _KJS_OBJECT_WRAPPER_H_
index 00b74bf..3f705c3 100644 (file)
@@ -232,6 +232,43 @@ ValueImp *PropertyMap::get(const Identifier &name) const
     return 0;
 }
 
+ValueImp **PropertyMap::getLocation(const Identifier &name)
+{
+    assert(!name.isNull());
+    
+    UString::Rep *rep = name._ustring.rep;
+
+    if (!_table) {
+#if USE_SINGLE_ENTRY
+        UString::Rep *key = _singleEntry.key;
+        if (rep == key)
+            return &_singleEntry.value;
+#endif
+        return 0;
+    }
+    
+    unsigned h = rep->hash();
+    int sizeMask = _table->sizeMask;
+    Entry *entries = _table->entries;
+    int i = h & sizeMask;
+    int k = 0;
+#if DUMP_STATISTICS
+    ++numProbes;
+    numCollisions += entries[i].key && entries[i].key != rep;
+#endif
+    while (UString::Rep *key = entries[i].key) {
+        if (rep == key)
+            return &entries[i].value;
+        if (k == 0)
+            k = 1 | (h % sizeMask);
+        i = (i + k) & sizeMask;
+#if DUMP_STATISTICS
+        ++numRehashes;
+#endif
+    }
+    return 0;
+}
+
 #if DEBUG_PROPERTIES
 static void printAttributes(int attributes)
 {
index b7df638..8450271 100644 (file)
@@ -78,6 +78,7 @@ namespace KJS {
         void remove(const Identifier &name);
         ValueImp *get(const Identifier &name) const;
         ValueImp *get(const Identifier &name, int &attributes) const;
+        ValueImp **getLocation(const Identifier &name);
 
         void mark() const;
         void addEnumerablesToReferenceList(ReferenceList &, const Object &) const;
diff --git a/JavaScriptCore/kjs/property_slot.cpp b/JavaScriptCore/kjs/property_slot.cpp
new file mode 100644 (file)
index 0000000..8b44a80
--- /dev/null
@@ -0,0 +1,33 @@
+// -*- c-basic-offset: 4 -*-
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2005 Apple Computer, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#include "property_slot.h"
+
+namespace KJS {
+
+Value PropertySlot::undefinedGetter(ExecState *, const Identifier& propertyName, const PropertySlot& slot)
+{
+    return Undefined();
+}
+
+}
diff --git a/JavaScriptCore/kjs/property_slot.h b/JavaScriptCore/kjs/property_slot.h
new file mode 100644 (file)
index 0000000..dad6913
--- /dev/null
@@ -0,0 +1,109 @@
+// -*- c-basic-offset: 4 -*-
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2005 Apple Computer, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _KJS_PROPERTY_SLOT_H_
+#define _KJS_PROPERTY_SLOT_H_
+
+#include "identifier.h"
+#include "value.h"
+
+namespace KJS {
+
+class HashEntry;
+class ExecState;
+class ObjectImp;
+
+#define VALUE_SLOT_MARKER ((GetValueFunc)1)
+class PropertySlot
+{
+public:
+    typedef Value (*GetValueFunc)(ExecState *, const Identifier&, const PropertySlot&);
+
+    bool isSet() { return m_getValue != 0; }
+    Value getValue(ExecState *exec, const Identifier& propertyName) const
+    { 
+        if (m_getValue == VALUE_SLOT_MARKER)
+            return *m_data.valueSlot;
+        return m_getValue(exec, propertyName, *this); 
+    }
+
+    Value getValue(ExecState *exec, unsigned propertyName) const
+    { 
+        if (m_getValue == VALUE_SLOT_MARKER)
+            return *m_data.valueSlot;
+        return m_getValue(exec, Identifier::from(propertyName), *this); 
+    }
+    
+    void setValueSlot(ObjectImp *slotBase, ValueImp **valueSlot) 
+    {
+        m_slotBase = slotBase;
+        m_data.valueSlot = valueSlot;
+        m_getValue = VALUE_SLOT_MARKER;
+    }
+
+    void setStaticEntry(ObjectImp *slotBase, const HashEntry *staticEntry, GetValueFunc getValue)
+    {
+        m_slotBase = slotBase;
+        m_data.staticEntry = staticEntry;
+        m_getValue = getValue;
+    }
+
+    void setCustom(ObjectImp *slotBase, GetValueFunc getValue)
+    {
+        m_slotBase = slotBase;
+        m_getValue = getValue;
+    }
+
+    void setCustomIndex(ObjectImp *slotBase, unsigned long index, GetValueFunc getValue)
+    {
+        m_slotBase = slotBase;
+        m_data.index = index;
+        m_getValue = getValue;
+    }
+
+    void setUndefined(ObjectImp *slotBase)
+    {
+        m_slotBase = slotBase;
+        m_getValue = undefinedGetter;
+    }
+
+    ObjectImp *slotBase() const { return m_slotBase; }
+
+    const HashEntry *staticEntry() const { return m_data.staticEntry; }
+    unsigned long index() const { return m_data.index; }
+
+private:
+    static Value undefinedGetter(ExecState *, const Identifier&, const PropertySlot&);
+
+    GetValueFunc m_getValue;
+
+    ObjectImp *m_slotBase;
+    union {
+        ValueImp **valueSlot;
+        const HashEntry *staticEntry;
+        unsigned long index;
+    } m_data;
+};
+
+}
+
+#endif _KJS_PROPERTY_SLOT_H_
index 783bedb..6b39e4e 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _KJS_PROTECT_H_
 #define _KJS_PROTECT_H_
 
-#include "object.h"
 #include "reference.h"
 #include "value.h"
 #include "protected_values.h"
@@ -77,56 +76,6 @@ namespace KJS {
       explicit ProtectedValue(ValueImp *v);
     };
 
-
-    class ProtectedObject : public Object {
-    public:
-      ProtectedObject() : Object() {}
-      ProtectedObject(const Object &o)  : Object(o) { gcProtectNullTolerant(o.imp()); };
-      ProtectedObject(const ProtectedObject &o)  : Object(o) { gcProtectNullTolerant(o.imp()); };
-      ~ProtectedObject() { gcUnprotectNullTolerant(imp());}
-      ProtectedObject& operator=(const Object &o)
-       { 
-         ValueImp *old = imp();
-         Object::operator=(o); 
-         gcProtectNullTolerant(o.imp());
-         gcUnprotectNullTolerant(old); 
-         return *this;
-       }
-      ProtectedObject& operator=(const ProtectedObject &o)
-       { 
-         ValueImp *old = imp();
-         Object::operator=(o); 
-         gcProtectNullTolerant(o.imp());
-         gcUnprotectNullTolerant(old); 
-         return *this;
-       }
-    private:
-      explicit ProtectedObject(ObjectImp *o);
-    };
-
-
-    class ProtectedReference : public Reference {
-    public:
-      ProtectedReference(const Reference&r)  : Reference(r) { gcProtectNullTolerant(r.base.imp()); };
-      ~ProtectedReference() { gcUnprotectNullTolerant(base.imp());}
-      ProtectedReference& operator=(const Reference &r)
-       { 
-         ValueImp *old = base.imp();
-         Reference::operator=(r); 
-         gcProtectNullTolerant(r.base.imp());
-         gcUnprotectNullTolerant(old); 
-         return *this;
-       }
-    private:
-      ProtectedReference();
-      ProtectedReference(const Object& b, const Identifier& p);
-      ProtectedReference(const Object& b, unsigned p);
-      ProtectedReference(ObjectImp *b, const Identifier& p);
-      ProtectedReference(ObjectImp *b, unsigned p);
-      ProtectedReference(const Null& b, const Identifier& p);
-      ProtectedReference(const Null& b, unsigned p);
-    };
-
-}
+} // namespace
 
 #endif
diff --git a/JavaScriptCore/kjs/protected_object.h b/JavaScriptCore/kjs/protected_object.h
new file mode 100644 (file)
index 0000000..e267657
--- /dev/null
@@ -0,0 +1,84 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2004 Apple Computer, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ *  Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef _KJS_PROTECTED_OBJECT_H_
+#define _KJS_PROTECTED_OBJECT_H_
+
+#include "protect.h"
+#include "object.h"
+#include "reference.h"
+
+namespace KJS {
+
+    class ProtectedObject : public Object {
+    public:
+      ProtectedObject() : Object() {}
+      ProtectedObject(const Object &o)  : Object(o) { gcProtectNullTolerant(o.imp()); };
+      ProtectedObject(const ProtectedObject &o)  : Object(o) { gcProtectNullTolerant(o.imp()); };
+      ~ProtectedObject() { gcUnprotectNullTolerant(imp());}
+      ProtectedObject& operator=(const Object &o)
+       { 
+         ValueImp *old = imp();
+         Object::operator=(o); 
+         gcProtectNullTolerant(o.imp());
+         gcUnprotectNullTolerant(old); 
+         return *this;
+       }
+      ProtectedObject& operator=(const ProtectedObject &o)
+       { 
+         ValueImp *old = imp();
+         Object::operator=(o); 
+         gcProtectNullTolerant(o.imp());
+         gcUnprotectNullTolerant(old); 
+         return *this;
+       }
+    private:
+      explicit ProtectedObject(ObjectImp *o);
+    };
+
+
+    class ProtectedReference : public Reference {
+    public:
+      ProtectedReference(const Reference&r)  : Reference(r) { gcProtectNullTolerant(r.base.imp()); };
+      ~ProtectedReference() { gcUnprotectNullTolerant(base.imp());}
+      ProtectedReference& operator=(const Reference &r)
+       { 
+         ValueImp *old = base.imp();
+         Reference::operator=(r); 
+         gcProtectNullTolerant(r.base.imp());
+         gcUnprotectNullTolerant(old); 
+         return *this;
+       }
+    private:
+      ProtectedReference();
+      ProtectedReference(const Object& b, const Identifier& p);
+      ProtectedReference(const Object& b, unsigned p);
+      ProtectedReference(ObjectImp *b, const Identifier& p);
+      ProtectedReference(ObjectImp *b, unsigned p);
+      ProtectedReference(const Null& b, const Identifier& p);
+      ProtectedReference(const Null& b, unsigned p);
+    };
+
+} // namespace
+
+#endif
index 00ec49b..4a4ec3a 100644 (file)
@@ -28,6 +28,9 @@
 
 namespace KJS {
 
+  class Object;
+  class ObjectImp;
+
   class Reference {
     friend class ReferenceList;
     friend class ReferenceListIterator;
index 0bd0041..6d0b276 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "reference_list.h"
 
-#include "protect.h"
+#include "protected_object.h"
 
 namespace KJS {
   class ReferenceListNode {
index 193f9fe..8f5d945 100644 (file)
@@ -216,27 +216,35 @@ Object RegExpObjectImp::arrayOfMatches(ExecState *exec, const UString &result) c
   return arr;
 }
 
-bool RegExpObjectImp::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value RegExpObjectImp::backrefGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
 {
-  UString s = p.ustring();
+  RegExpObjectImp *thisObj = static_cast<RegExpObjectImp *>(slot.slotBase());
+  unsigned long i = slot.index();
+
+  if (i < thisObj->lastNrSubPatterns + 1) {
+    int *lastOvector = thisObj->lastOvector;
+    UString substring = thisObj->lastString.substr(lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
+    return String(substring);
+  } 
+
+  return String("");
+}
+
+bool RegExpObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  UString s = propertyName.ustring();
   if (s[0] == '$' && lastOvector)
   {
     bool ok;
     unsigned long i = s.substr(1).toULong(&ok);
     if (ok)
     {
-      if (i < lastNrSubPatterns + 1)
-      {
-        UString substring = lastString.substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
-        result = String(substring);
-      } else
-        result = String("");
-      
+      slot.setCustomIndex(this, i, backrefGetter);
       return true;
     }
   }
 
-  return InternalFunctionImp::getOwnProperty(exec, p, result);
+  return InternalFunctionImp::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 bool RegExpObjectImp::implementsConstruct() const
index e890d94..5b0eeb9 100644 (file)
@@ -74,11 +74,13 @@ namespace KJS {
     virtual bool implementsCall() const;
     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     int ** registerRegexp( const RegExp* re, const UString& s );
     void setSubPatterns(int num) { lastNrSubPatterns = num; }
     Object arrayOfMatches(ExecState *exec, const UString &result) const;
   private:
+    static Value backrefGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+  
     UString lastString;
     int *lastOvector;
     uint lastNrSubPatterns;
index f484051..36563c3 100644 (file)
@@ -50,10 +50,21 @@ StringInstanceImp::StringInstanceImp(ObjectImp *proto, const UString &string)
   setInternalValue(String(string));
 }
 
-bool StringInstanceImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value StringInstanceImp::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot &slot)
+{
+    return Value(static_cast<StringInstanceImp *>(slot.slotBase())->internalValue().toString(exec).size());
+}
+
+Value StringInstanceImp::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot &slot)
+{
+    const UChar c = static_cast<StringInstanceImp *>(slot.slotBase())->internalValue().toString(exec)[slot.index()];
+    return Value(UString(&c, 1));
+}
+
+bool StringInstanceImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
 {
   if (propertyName == lengthPropertyName) {
-    result = Value(internalValue().toString(exec).size());
+    slot.setCustom(this, lengthGetter);
     return true;
   }
 
@@ -63,13 +74,12 @@ bool StringInstanceImp::getOwnProperty(ExecState *exec, const Identifier& proper
     const UString s = internalValue().toString(exec);
     const unsigned length = s.size();
     if (index >= length)
-      return Undefined();
-    const UChar c = s[index];
-    result = Value(UString(&c, 1));
+      return false;
+    slot.setCustomIndex(this, index, indexGetter);
     return true;
   }
 
-  return ObjectImp::getOwnProperty(exec, propertyName, result);
+  return ObjectImp::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 void StringInstanceImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
@@ -79,22 +89,6 @@ void StringInstanceImp::put(ExecState *exec, const Identifier &propertyName, con
   ObjectImp::put(exec, propertyName, value, attr);
 }
 
-bool StringInstanceImp::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
-{
-  if (propertyName == lengthPropertyName)
-    return true;
-
-  bool ok;
-  const unsigned index = propertyName.toArrayIndex(&ok);
-  if (ok) {
-    const unsigned length = internalValue().toString(exec).size();
-    if (index < length)
-      return true;
-  }
-
-  return ObjectImp::hasOwnProperty(exec, propertyName);
-}
-
 bool StringInstanceImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
 {
   if (propertyName == lengthPropertyName)
@@ -154,9 +148,9 @@ StringPrototypeImp::StringPrototypeImp(ExecState *exec,
 
 }
 
-bool StringPrototypeImp::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool StringPrototypeImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
 {
-  return lookupGetOwnFunction<StringProtoFuncImp, StringInstanceImp>(exec, propertyName, &stringTable, this, result);
+  return getStaticFunctionSlot<StringProtoFuncImp, StringInstanceImp>(exec, &stringTable, this, propertyName, slot);
 }
 
 // ------------------------------ StringProtoFuncImp ---------------------------
index d2a4a9f..7cce991 100644 (file)
@@ -32,13 +32,15 @@ namespace KJS {
     StringInstanceImp(ObjectImp *proto);
     StringInstanceImp(ObjectImp *proto, const UString &string);
 
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None);
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
 
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
+  private:
+    static Value lengthGetter(ExecState *exec, const Identifier&, const PropertySlot &slot);
+    static Value indexGetter(ExecState *exec, const Identifier&, const PropertySlot &slot);
   };
 
   /**
@@ -51,7 +53,7 @@ namespace KJS {
   public:
     StringPrototypeImp(ExecState *exec,
                        ObjectPrototypeImp *objProto);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
   };
diff --git a/LayoutTests/fast/js/string-index-overflow-expected.txt b/LayoutTests/fast/js/string-index-overflow-expected.txt
new file mode 100644 (file)
index 0000000..81a978c
--- /dev/null
@@ -0,0 +1,6 @@
+This test checks that accessing a string by an out of bounds index doesn't crash, furthermore the string should not appear to have out-of-bounds numeric properties. Below you should see "undefined" followed by "false".
+
+undefined
+false
+
+
diff --git a/LayoutTests/fast/js/string-index-overflow.html b/LayoutTests/fast/js/string-index-overflow.html
new file mode 100644 (file)
index 0000000..220e547
--- /dev/null
@@ -0,0 +1,15 @@
+<p>
+This test checks that accessing a string by an out of bounds index
+doesn't crash, furthermore the string should not appear to have
+out-of-bounds numeric properties. Below you should see "undefined"
+followed by "false".
+</p>
+<hr>
+<pre>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+document.writeln("x"[10]);
+document.writeln("x".hasOwnProperty(10));
+</script>
+</pre>
\ No newline at end of file
index dec8c16..3eb2d79 100644 (file)
@@ -420,7 +420,7 @@ namespace KDOM
                KJS::Value getValueProperty(KJS::ExecState *exec, int token) const;
                void putValueProperty(KJS::ExecState *exec, int token, const KJS::Value &value, int attr);              
        };
-};
+}
 
 KDOM_DEFINE_PROTOTYPE(DocumentProto)
 KDOM_IMPLEMENT_PROTOFUNC(DocumentProtoFunc, Document)
index 9286afd..66b909d 100644 (file)
@@ -504,7 +504,7 @@ T &T::operator=(const KDOM::Node &other) \
        return *this; \
 }
 
-};
+}
 
 KDOM_DEFINE_PROTOTYPE(NodeProto)
 KDOM_IMPLEMENT_PROTOFUNC(NodeProtoFunc, Node)
index f3fa71c..3b1522d 100644 (file)
@@ -143,6 +143,7 @@ namespace KDOM
                                                                const ThisImp *thisObj, // the 'impl' object
                                                                const KJS::ObjectImp *bridge)
        {
+#if 0
                const KJS::HashEntry *entry = KJS::Lookup::findEntry(table, propertyName);
 
                if(!entry) // not found, forward to parents
@@ -154,6 +155,8 @@ namespace KDOM
                                                                                                                entry->value, entry->params, entry->attr);
 
                return thisObj->getValueProperty(exec, entry->value);
+#endif
+                return KJS::Undefined();
        }
 
        /**
@@ -167,6 +170,7 @@ namespace KDOM
                                                                         const ThisImp *thisObj, // the 'impl' object
                                      const KJS::ObjectImp *bridge)
        {
+#if 0
                const KJS::HashEntry *entry = KJS::Lookup::findEntry(table, propertyName);
 
                if(!entry) // not found, forward to parents
@@ -176,6 +180,8 @@ namespace KDOM
                        kdError(26004) << "Function bit set! Shouldn't happen in lookupGetValue! propertyName was " << propertyName.qstring() << endl;
 
                return thisObj->getValueProperty(exec, entry->value);
+#endif
+                return KJS::Undefined();
        }
 
        /**
@@ -246,7 +252,7 @@ namespace KDOM
     static const struct KJS::HashTable s_hashTable; \
   }; \
   KJS::Value get##ClassName(KJS::ExecState *exec); \
-  };
+  }
 
 // Same as kjs' DEFINE_PROTOTYPE, but with a pointer to the hashtable too, and no ClassName here
 // The ClassProto ctor(exec) must be public, so we can use KJS::cacheGlobalObject... (Niko)
@@ -264,16 +270,16 @@ namespace KDOM
     \
     static const struct KJS::HashTable s_hashTable; \
   }; \
-  };
+  }
 
 // same as IMPLEMENT_PROTOTYPE but in the KDOM namespace, and with ClassName here
 // so that KDOM_DEFINE_PROTOTYPE can be put in a header file ('info' defined here)
 #define ECMA_IMPLEMENT_PROTOTYPE(Space,ClassName,ClassProto,ClassFunc) \
     KJS::Value Space::ClassProto::get(KJS::ExecState *exec, const KJS::Identifier &propertyName) const \
     { \
-        KJS::Value result; \
+        /* KJS::Value result; \
         if (KJS::lookupGetOwnFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &s_hashTable, this, result)) \
-            return result; \
+        return result;  */ \
         return KJS::Undefined(); \
       /* return KJS::lookupGetFunction<ClassFunc,KJS::ObjectImp>(exec, propertyName, &s_hashTable, this ); */ \
     } \
@@ -309,7 +315,7 @@ namespace KDOM
   }; \
   /* Is eventually generated, if KDOM_CAST is given */ \
      Class to##Class(KJS::ExecState *exec, const KJS::ObjectImp *bridge); \
-  };
+  }
 
 // To be used when casting the type of an argument
 #define KDOM_CHECK(ClassName, theObj) \
index 88a32af..12be74d 100644 (file)
@@ -162,9 +162,11 @@ KJS::Value GlobalObject::get(KJS::ExecState *exec, const KJS::Identifier &p) con
                        case GlobalObjectConstants::Debug:
                        case GlobalObjectConstants::Prompt:
                        {
+#if 0
                                if(isSafeScript(exec))
                                        return KJS::lookupOrCreateFunction<GlobalObjectFunc>(exec, p, this, entry->value, entry->params, entry->attr);
                                else
+#endif
                                        return KJS::Undefined();
                        }
                        case GlobalObjectConstants::Node:
index f06340a..e50d0f0 100644 (file)
@@ -65,7 +65,7 @@ namespace KDOM
 
                KJS::Value getValueProperty(KJS::ExecState *exec, int token) const;
        };
-};
+}
 
 KDOM_DEFINE_PROTOTYPE(EventTargetProto)
 KDOM_IMPLEMENT_PROTOFUNC(EventTargetProtoFunc, EventTarget)
index a4c0a5f..aaeed3f 100644 (file)
@@ -1,3 +1,182 @@
+2005-08-04  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       Change over to the new PropertySlot mechanism for property
+       lookup. This allows the elimination of hasOwnProperty methods. I
+       also did a bunch of code cleanup and regularization of the various
+       property lookup methods.
+       
+        Test cases added: Added a test case for a bug I found along the way.
+        * layout-tests/fast/js/string-index-overflow.html:
+       * layout-tests/fast/js/string-index-overflow-expected.txt:
+       
+        * khtml/ecma/kjs_binding.cpp:
+        (KJS::ScriptInterpreter::createLanguageInstanceForValue):
+        * khtml/ecma/kjs_binding.h:
+        * khtml/ecma/kjs_css.cpp:
+        (KJS::DOMCSSStyleDeclaration::indexGetter):
+        (KJS::DOMCSSStyleDeclaration::cssPropertyGetter):
+        (KJS::DOMCSSStyleDeclaration::getOwnPropertySlot):
+        (KJS::DOMCSSStyleDeclaration::getValueProperty):
+        (KJS::DOMStyleSheet::getOwnPropertySlot):
+        (KJS::DOMStyleSheetList::getValueProperty):
+        (KJS::DOMStyleSheetList::indexGetter):
+        (KJS::DOMStyleSheetList::nameGetter):
+        (KJS::DOMStyleSheetList::getOwnPropertySlot):
+        (KJS::DOMMediaList::getValueProperty):
+        (KJS::DOMMediaList::indexGetter):
+        (KJS::DOMMediaList::getOwnPropertySlot):
+        (KJS::DOMCSSStyleSheet::getValueProperty):
+        (KJS::DOMCSSStyleSheet::getOwnPropertySlot):
+        (KJS::DOMCSSRuleList::getValueProperty):
+        (KJS::DOMCSSRuleList::indexGetter):
+        (KJS::DOMCSSRuleList::getOwnPropertySlot):
+        (KJS::DOMCSSRule::getOwnPropertySlot):
+        (KJS::CSSRuleConstructor::getOwnPropertySlot):
+        (KJS::DOMCSSValue::getValueProperty):
+        (KJS::DOMCSSValue::getOwnPropertySlot):
+        (KJS::CSSValueConstructor::getOwnPropertySlot):
+        (KJS::DOMCSSPrimitiveValue::getValueProperty):
+        (KJS::DOMCSSPrimitiveValue::getOwnPropertySlot):
+        (KJS::CSSPrimitiveValueConstructor::getOwnPropertySlot):
+        (KJS::DOMCSSValueList::getValueProperty):
+        (KJS::DOMCSSValueList::indexGetter):
+        (KJS::DOMCSSValueList::getOwnPropertySlot):
+        (KJS::DOMRGBColor::getOwnPropertySlot):
+        (KJS::DOMRect::getOwnPropertySlot):
+        (KJS::DOMCounter::getOwnPropertySlot):
+        * khtml/ecma/kjs_css.h:
+        (KJS::DOMCSSStyleDeclaration::):
+        (KJS::DOMCSSStyleSheet::):
+        (KJS::DOMCSSRule::):
+        (KJS::DOMCSSValueList::):
+        * khtml/ecma/kjs_dom.cpp:
+        (KJS::DOMNode::getOwnPropertySlot):
+        (KJS::):
+        (KJS::DOMNodeList::getValueProperty):
+        (KJS::DOMNodeList::indexGetter):
+        (KJS::DOMNodeList::nameGetter):
+        (KJS::DOMNodeList::getOwnPropertySlot):
+        (KJS::DOMNodeList::call):
+        (KJS::DOMAttr::getOwnPropertySlot):
+        (KJS::DOMDocument::getOwnPropertySlot):
+        (KJS::DOMElement::getValueProperty):
+        (KJS::DOMElement::attributeGetter):
+        (KJS::DOMElement::getOwnPropertySlot):
+        (KJS::DOMDocumentType::getOwnPropertySlot):
+        (KJS::DOMNamedNodeMap::lengthGetter):
+        (KJS::DOMNamedNodeMap::indexGetter):
+        (KJS::DOMNamedNodeMap::getOwnPropertySlot):
+        (KJS::DOMProcessingInstruction::getOwnPropertySlot):
+        (KJS::DOMNotation::getOwnPropertySlot):
+        (KJS::DOMEntity::getOwnPropertySlot):
+        (KJS::NodeConstructor::getOwnPropertySlot):
+        (KJS::DOMExceptionConstructor::getOwnPropertySlot):
+        (KJS::DOMNamedNodesCollection::lengthGetter):
+        (KJS::DOMNamedNodesCollection::indexGetter):
+        (KJS::DOMNamedNodesCollection::getOwnPropertySlot):
+        (KJS::DOMCharacterData::getOwnPropertySlot):
+        * khtml/ecma/kjs_dom.h:
+        * khtml/ecma/kjs_events.cpp:
+        (KJS::EventConstructor::getOwnPropertySlot):
+        (KJS::DOMEvent::getOwnPropertySlot):
+        (KJS::EventExceptionConstructor::getOwnPropertySlot):
+        (KJS::DOMUIEvent::getOwnPropertySlot):
+        (KJS::DOMMouseEvent::getOwnPropertySlot):
+        (KJS::DOMKeyboardEvent::getOwnPropertySlot):
+        (KJS::MutationEventConstructor::getOwnPropertySlot):
+        (KJS::DOMMutationEvent::getOwnPropertySlot):
+        (KJS::DOMWheelEvent::getOwnPropertySlot):
+        (KJS::Clipboard::getOwnPropertySlot):
+        * khtml/ecma/kjs_events.h:
+        * khtml/ecma/kjs_html.cpp:
+        (KJS::HTMLDocument::namedItemGetter):
+        (KJS::HTMLDocument::getValueProperty):
+        (KJS::HTMLDocument::getOwnPropertySlot):
+        (KJS::HTMLElement::formIndexGetter):
+        (KJS::HTMLElement::formNameGetter):
+        (KJS::HTMLElement::selectIndexGetter):
+        (KJS::HTMLElement::framesetNameGetter):
+        (KJS::HTMLElement::frameWindowPropertyGetter):
+        (KJS::HTMLElement::runtimeObjectGetter):
+        (KJS::HTMLElement::runtimeObjectPropertyGetter):
+        (KJS::HTMLElement::getOwnPropertySlot):
+        (KJS::HTMLCollection::lengthGetter):
+        (KJS::HTMLCollection::indexGetter):
+        (KJS::HTMLCollection::nameGetter):
+        (KJS::HTMLCollection::getOwnPropertySlot):
+        (KJS::HTMLSelectCollection::selectedIndexGetter):
+        (KJS::HTMLSelectCollection::getOwnPropertySlot):
+        (KJS::Image::getOwnPropertySlot):
+        (KJS::Context2D::getOwnPropertySlot):
+        (KJS::Gradient::getOwnPropertySlot):
+        (KJS::ImagePattern::getOwnPropertySlot):
+        * khtml/ecma/kjs_html.h:
+        (KJS::HTMLCollection::toBoolean):
+        * khtml/ecma/kjs_navigator.cpp:
+        (KJS::Plugins::):
+        (KJS::MimeTypes::):
+        (KJS::Plugin::):
+        (KJS::MimeType::):
+        (KJS::):
+        (KJS::Navigator::getOwnPropertySlot):
+        (KJS::Plugins::getValueProperty):
+        (KJS::Plugins::indexGetter):
+        (KJS::Plugins::nameGetter):
+        (KJS::Plugins::getOwnPropertySlot):
+        (KJS::MimeTypes::getValueProperty):
+        (KJS::MimeTypes::indexGetter):
+        (KJS::MimeTypes::nameGetter):
+        (KJS::MimeTypes::getOwnPropertySlot):
+        (KJS::Plugin::getValueProperty):
+        (KJS::Plugin::indexGetter):
+        (KJS::Plugin::nameGetter):
+        (KJS::Plugin::getOwnPropertySlot):
+        (KJS::MimeType::getValueProperty):
+        (KJS::MimeType::getOwnPropertySlot):
+        * khtml/ecma/kjs_navigator.h:
+        * khtml/ecma/kjs_range.cpp:
+        (KJS::DOMRange::getOwnPropertySlot):
+        (KJS::RangeConstructor::getOwnPropertySlot):
+        * khtml/ecma/kjs_range.h:
+        * khtml/ecma/kjs_traversal.cpp:
+        (KJS::DOMNodeIterator::getOwnPropertySlot):
+        (KJS::NodeFilterConstructor::getOwnPropertySlot):
+        (KJS::DOMTreeWalker::getOwnPropertySlot):
+        * khtml/ecma/kjs_traversal.h:
+        * khtml/ecma/kjs_views.cpp:
+        (KJS::DOMAbstractView::~DOMAbstractView):
+        (KJS::DOMAbstractView::getValueProperty):
+        (KJS::DOMAbstractView::getOwnPropertySlot):
+        * khtml/ecma/kjs_views.h:
+        * khtml/ecma/kjs_window.cpp:
+        (KJS::FrameArray::):
+        (KJS::FrameArray::classInfo):
+        (KJS::Screen::getOwnPropertySlot):
+        (KJS::Window::getValueProperty):
+        (KJS::Window::childFrameGetter):
+        (KJS::Window::namedFrameGetter):
+        (KJS::Window::indexGetter):
+        (KJS::Window::namedItemGetter):
+        (KJS::Window::getOwnPropertySlot):
+        (KJS::):
+        (KJS::FrameArray::getValueProperty):
+        (KJS::FrameArray::indexGetter):
+        (KJS::FrameArray::nameGetter):
+        (KJS::FrameArray::getOwnPropertySlot):
+        (KJS::Location::getValueProperty):
+        (KJS::Location::getOwnPropertySlot):
+        (KJS::Selection::getValueProperty):
+        (KJS::Selection::getOwnPropertySlot):
+        (KJS::BarInfo::getValueProperty):
+        (KJS::BarInfo::getOwnPropertySlot):
+        (KJS::History::getOwnPropertySlot):
+        * khtml/ecma/kjs_window.h:
+        * khtml/ecma/xmlhttprequest.cpp:
+        (KJS::XMLHttpRequest::getOwnPropertySlot):
+        * khtml/ecma/xmlhttprequest.h:
+
 2005-08-06  Eric Seidel  <eseidel@apple.com>
 
         Reviewed by darin.
diff --git a/WebCore/ForwardingHeaders/kjs/protected_object.h b/WebCore/ForwardingHeaders/kjs/protected_object.h
new file mode 100644 (file)
index 0000000..61fcdae
--- /dev/null
@@ -0,0 +1 @@
+#import <JavaScriptCore/protected_object.h>
index 618e91d..6ca6877 100644 (file)
@@ -228,7 +228,7 @@ Interpreter *ScriptInterpreter::interpreterForGlobalObject (const ValueImp *imp)
     return win->interpreter();
 }
 
-void *ScriptInterpreter::createLanguageInstanceForValue (ExecState *exec, Bindings::Instance::BindingLanguage language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current)
+void *ScriptInterpreter::createLanguageInstanceForValue (ExecState *exec, int language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current)
 {
     void *result = 0;
     
index 030559b..dfccffc 100644 (file)
@@ -25,7 +25,6 @@
 #include <kjs/interpreter.h>
 #include <qvariant.h>
 #include <kjs/lookup.h>
-#include <kjs/protect.h>
 
 #if APPLE_CHANGES
 #include <JavaScriptCore/runtime.h>
@@ -111,7 +110,7 @@ namespace KJS {
     virtual bool isGlobalObject(const Value &v);
     virtual Interpreter *interpreterForGlobalObject (const ValueImp *imp);
     virtual bool isSafeScript (const Interpreter *target);
-    virtual void *createLanguageInstanceForValue (ExecState *exec, Bindings::Instance::BindingLanguage language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current);
+    virtual void *createLanguageInstanceForValue (ExecState *exec, int language, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current);
     void *createObjcInstanceForValue (ExecState *exec, const Object &value, const Bindings::RootObject *origin, const Bindings::RootObject *current);
 #endif
 
index 65bf94f..9a248cf 100644 (file)
@@ -134,78 +134,71 @@ DOMCSSStyleDeclaration::~DOMCSSStyleDeclaration()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMCSSStyleDeclaration::hasOwnProperty(ExecState *exec, const Identifier &p) const
+Value DOMCSSStyleDeclaration::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
 {
-  if (p == "cssText")
-    return true;
-  if (isCSSPropertyName(p))
-    return true;
-  return ObjectImp::hasOwnProperty(exec, p);
+  DOMCSSStyleDeclaration *thisObj = static_cast<DOMCSSStyleDeclaration *>(slot.slotBase());
+  return getStringOrNull(thisObj->m_impl->item(slot.index()));
 }
 
-bool DOMCSSStyleDeclaration::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value DOMCSSStyleDeclaration::cssPropertyGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMCSSStyleDeclaration *thisObj = static_cast<DOMCSSStyleDeclaration *>(slot.slotBase());
+
+  // Set up pixelOrPos boolean to handle the fact that
+  // pixelTop returns "CSS Top" as number value in unit pixels
+  // posTop returns "CSS top" as number value in unit pixels _if_ its a
+  // positioned element. if it is not a positioned element, return 0
+  // from MSIE documentation ### IMPLEMENT THAT (Dirk)
+  bool pixelOrPos;
+  DOMString prop = cssPropertyName(propertyName, &pixelOrPos);
+  CSSValueImpl *v = thisObj->m_impl->getPropertyCSSValue(prop);
+  if (v) {
+    if (pixelOrPos && v->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE)
+      return Number(static_cast<CSSPrimitiveValueImpl *>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX));
+    else
+      return getStringOrNull(v->cssText());
+  } else
+    return String("");
+}
+
+bool DOMCSSStyleDeclaration::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-#ifdef KJS_VERBOSE
-  kdDebug(6070) << "DOMCSSStyleDeclaration::get " << propertyName.qstring() << endl;
-#endif
   const HashEntry* entry = Lookup::findEntry(&DOMCSSStyleDeclarationTable, propertyName);
-  CSSStyleDeclarationImpl &styleDecl = *m_impl;
+
   if (entry) {
-    switch (entry->value) {
-    case CssText:
-      result = getStringOrNull(styleDecl.cssText());
-      return true;
-    case Length:
-      result = Value(styleDecl.length());
-      return true;
-    case ParentRule:
-      result = getDOMCSSRule(exec,styleDecl.parentRule());
-      return true;
-    default:
-      assert(0);
-    }
+    slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSStyleDeclaration>);
+    return true;
   }
 
-  // Look in the prototype (for functions) before assuming it's a name
-  // FIXME: is this really needed? do any property names conflict with names
-  // of functions from the prototype?
-  Object proto = Object::dynamicCast(prototype());
-  if (!proto.isNull() && proto.hasProperty(exec,propertyName))
-    return false;
-
   bool ok;
   long unsigned int u = propertyName.toULong(&ok);
   if (ok) {
-    result = getStringOrNull(styleDecl.item(u));
+    slot.setCustomIndex(this, u, indexGetter);
     return true;
   }
 
-#ifdef KJS_VERBOSE
-  kdDebug(6070) << "DOMCSSStyleDeclaration: converting to css property name: " << cssPropertyName(propertyName) << endl;
-#endif
-
-  // Set up pixelOrPos boolean to handle the fact that
-  // pixelTop returns "CSS Top" as number value in unit pixels
-  // posTop returns "CSS top" as number value in unit pixels _if_ its a
-  // positioned element. if it is not a positioned element, return 0
-  // from MSIE documentation ### IMPLEMENT THAT (Dirk)
   if (isCSSPropertyName(propertyName)) {
-    bool pixelOrPos;
-    DOMString prop = cssPropertyName(propertyName, &pixelOrPos);
-    CSSValueImpl *v = styleDecl.getPropertyCSSValue(prop);
-    if (v) {
-      if (pixelOrPos && v->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE)
-        result = Number(static_cast<CSSPrimitiveValueImpl *>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX));
-      else
-        result =  getStringOrNull(v->cssText());
-    } else
-      result = String("");
+    slot.setCustom(this, cssPropertyGetter);
     return true;
   }
 
-  return DOMObject::getOwnProperty(exec, propertyName, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
+Value DOMCSSStyleDeclaration::getValueProperty(ExecState *exec, int token)
+{
+  switch (token) {
+  case CssText:
+    return getStringOrNull(m_impl->cssText());
+  case Length:
+    return Value(m_impl->length());
+  case ParentRule:
+    return getDOMCSSRule(exec, m_impl->parentRule());
+  default:
+    assert(0);
+    return Undefined();
+  }
+}
 
 void DOMCSSStyleDeclaration::put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr )
 {
@@ -300,9 +293,9 @@ DOMStyleSheet::~DOMStyleSheet()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMStyleSheet::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMStyleSheet::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMStyleSheet, DOMObject>(exec, propertyName, &DOMStyleSheetTable, this, result);
+  return getStaticValueSlot<DOMStyleSheet, DOMObject>(exec, &DOMStyleSheetTable, this, propertyName, slot);
 }
 
 Value DOMStyleSheet::getValueProperty(ExecState *exec, int token) const
@@ -371,25 +364,52 @@ DOMStyleSheetList::~DOMStyleSheetList()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMStyleSheetList::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMStyleSheetList::getValueProperty(ExecState *exec, int token) const
 {
-#ifdef KJS_VERBOSE
-  kdDebug(6070) << "DOMStyleSheetList::get " << p.qstring() << endl;
-#endif
-  StyleSheetListImpl &styleSheetList = *m_impl;
-  if (p == lengthPropertyName) {
-    result = Number(styleSheetList.length());
-    return true;
-  } else if (p == "item") {
-    result = lookupOrCreateFunction<DOMStyleSheetListFunc>(exec, p, this, DOMStyleSheetList::Item, 1, DontDelete|Function);
-    return true;
+    switch(token) {
+    case Length:
+      return Number(m_impl->length());
+    default:
+      assert(0);
+      return Undefined();
+    }
+}
+
+Value DOMStyleSheetList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMStyleSheetList *thisObj = static_cast<DOMStyleSheetList *>(slot.slotBase());
+  return getDOMStyleSheet(exec, thisObj->m_impl->item(slot.index()));
+}
+
+Value DOMStyleSheetList::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMStyleSheetList *thisObj = static_cast<DOMStyleSheetList *>(slot.slotBase());
+  ElementImpl *element = thisObj->m_doc->getElementById(propertyName.string());
+  return getDOMStyleSheet(exec, static_cast<HTMLStyleElementImpl *>(element)->sheet());
+}
+
+bool DOMStyleSheetList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  const HashEntry* entry = Lookup::findEntry(&DOMStyleSheetListTable, propertyName);
+  
+  if (entry) {
+    switch(entry->value) {
+    case Length:
+      slot.setStaticEntry(this, entry, staticValueGetter<DOMStyleSheetList>);
+      return true;
+    case Item:
+      slot.setStaticEntry(this, entry, staticFunctionGetter<DOMStyleSheetListFunc>);
+      return true;
+    }
   }
 
+  StyleSheetListImpl &styleSheetList = *m_impl;
+
   // Retrieve stylesheet by index
   bool ok;
-  long unsigned int u = p.toULong(&ok);
-  if (ok) {
-    result = getDOMStyleSheet(exec, styleSheetList.item(u));
+  long unsigned int u = propertyName.toULong(&ok);
+  if (ok && u < styleSheetList.length()) {
+    slot.setCustomIndex(this, u, indexGetter);
     return true;
   }
 
@@ -419,13 +439,13 @@ bool DOMStyleSheetList::getOwnProperty(ExecState *exec, const Identifier& p, Val
   // ### Bad implementation because returns a single element (are IDs always unique?)
   // and doesn't look for name attribute (see implementation above).
   // But unicity of stylesheet ids is good practice anyway ;)
-  ElementImpl *element = m_doc->getElementById(p.string());
+  ElementImpl *element = m_doc->getElementById(propertyName.string());
   if (element && element->hasTagName(styleTag)) {
-    result = getDOMStyleSheet(exec, static_cast<HTMLStyleElementImpl *>(element)->sheet());
+    slot.setCustom(this, nameGetter);
     return true;
   }
 
-  return DOMObject::getOwnProperty(exec, p, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 ValueImp *getDOMStyleSheetList(ExecState *exec, StyleSheetListImpl *ssl, DocumentImpl *doc)
@@ -487,25 +507,41 @@ DOMMediaList::~DOMMediaList()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMMediaList::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMMediaList::getValueProperty(ExecState *exec, int token)
 {
-  MediaListImpl &mediaList = *m_impl;
-  if (p == "mediaText") {
-    result = getStringOrNull(mediaList.mediaText());
-    return true;
-  } else if (p == lengthPropertyName) {
-    result = Number(mediaList.length());
+  switch (token) {
+  case MediaText:
+    return getStringOrNull(m_impl->mediaText());
+  case Length:
+    return Number(m_impl->length());
+  default:
+    assert(0);
+    return Undefined();
+  }
+}
+
+Value DOMMediaList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMMediaList *thisObj = static_cast<DOMMediaList *>(slot.slotBase());
+  return getStringOrNull(thisObj->m_impl->item(slot.index()));
+}
+
+bool DOMMediaList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  const HashEntry* entry = Lookup::findEntry(&DOMMediaListTable, propertyName);
+  if (entry) {
+    slot.setStaticEntry(this, entry, staticValueGetter<DOMMediaList>);
     return true;
   }
 
   bool ok;
-  long unsigned int u = p.toULong(&ok);
-  if (ok) {
-    result = getStringOrNull(mediaList.item(u));
+  long unsigned int u = propertyName.toULong(&ok);
+  if (ok && u < m_impl->length()) {
+    slot.setCustomIndex(this, u, indexGetter);
     return true;
   }
 
-  return DOMObject::getOwnProperty(exec, p, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 void DOMMediaList::put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
@@ -576,17 +612,23 @@ DOMCSSStyleSheet::~DOMCSSStyleSheet()
 {
 }
 
-bool DOMCSSStyleSheet::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMCSSStyleSheet::getValueProperty(ExecState *exec, int token) const
 {
-  CSSStyleSheetImpl &cssStyleSheet = *static_cast<CSSStyleSheetImpl *>(impl());
-  if (p == "ownerRule") {
-    result = getDOMCSSRule(exec,cssStyleSheet.ownerRule());
-    return true;
-  } else if (p == "cssRules" || p == "rules" /* MSIE extension */) {
-    result =  getDOMCSSRuleList(exec,cssStyleSheet.cssRules());
-    return true;
+  switch (token) {
+  case OwnerRule:
+    return getDOMCSSRule(exec, static_cast<CSSStyleSheetImpl *>(impl())->ownerRule());
+  case CssRules:
+  case Rules:
+    return getDOMCSSRuleList(exec, static_cast<CSSStyleSheetImpl *>(impl())->cssRules());
+  default:
+    assert(0);
+    return Undefined();
   }
-  return DOMStyleSheet::getOwnProperty(exec, p, result);
+}
+
+bool DOMCSSStyleSheet::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  return getStaticValueSlot<DOMCSSStyleSheet, DOMStyleSheet>(exec, &DOMCSSStyleSheetTable, this, propertyName, slot);
 }
 
 Value DOMCSSStyleSheetProtoFunc::call(ExecState *exec, Object &thisObj, const List &args)
@@ -620,7 +662,7 @@ Value DOMCSSStyleSheetProtoFunc::call(ExecState *exec, Object &thisObj, const Li
 
 const ClassInfo DOMCSSRuleList::info = { "CSSRuleList", 0, &DOMCSSRuleListTable, 0 };
 /*
-@begin DOMCSSRuleListTable 3
+@begin DOMCSSRuleListTable 2
   length               DOMCSSRuleList::Length          DontDelete|ReadOnly
   item                 DOMCSSRuleList::Item            DontDelete|Function 1
 @end
@@ -632,25 +674,45 @@ DOMCSSRuleList::~DOMCSSRuleList()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMCSSRuleList::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMCSSRuleList::getValueProperty(ExecState *exec, int token) const
 {
-  CSSRuleListImpl &cssRuleList = *m_impl;
-  if (p == lengthPropertyName) {
-    result = Number(cssRuleList.length());
-    return true;
-  } else if (p == "item") {
-    result = lookupOrCreateFunction<DOMCSSRuleListFunc>(exec, p, this, DOMCSSRuleList::Item, 1, DontDelete|Function);
+  switch (token) {
+  case Length:
+    return Number(m_impl->length());
+  default:
+    assert(0);
+    return Undefined();
+  }
+}
+
+Value DOMCSSRuleList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMCSSRuleList *thisObj = static_cast<DOMCSSRuleList *>(slot.slotBase());
+  return getDOMCSSRule(exec, thisObj->m_impl->item(slot.index()));
+}
+
+bool DOMCSSRuleList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  const HashEntry* entry = Lookup::findEntry(&DOMCSSRuleListTable, propertyName);
+
+  if (entry) {
+    if (entry->attr & Function)
+      slot.setStaticEntry(this, entry, staticFunctionGetter<DOMCSSRuleListFunc>);
+    else
+      slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSRuleList>);
     return true;
   }
 
+  CSSRuleListImpl &cssRuleList = *m_impl;
+
   bool ok;
-  long unsigned int u = p.toULong(&ok);
-  if (ok) {
-    result = getDOMCSSRule(exec, cssRuleList.item(u));
+  long unsigned int u = propertyName.toULong(&ok);
+  if (ok && u < cssRuleList.length()) {
+    slot.setCustomIndex(this, u, indexGetter);
     return true;
   }
 
-  return DOMObject::getOwnProperty(exec, p, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 Value DOMCSSRuleListFunc::call(ExecState *exec, Object &thisObj, const List &args)
@@ -745,17 +807,17 @@ const ClassInfo* DOMCSSRule::classInfo() const
   encoding             DOMCSSRule::Charset_Encoding    DontDelete
 @end
 */
-bool DOMCSSRule::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMCSSRule::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
   // first try the properties specific to this rule type
   const HashEntry* entry = Lookup::findEntry(classInfo()->propHashTable, propertyName);
   if (entry) {
-    result = getValueProperty(exec, entry->value);
+    slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSRule>);
     return true;
   }
   
   // now the stuff that applies to all rules
-  return lookupGetOwnProperty<DOMCSSRuleFunc, DOMCSSRule, DOMObject>(exec, propertyName, &DOMCSSRuleTable, this, result);
+  return getStaticPropertySlot<DOMCSSRuleFunc, DOMCSSRule, DOMObject>(exec, &DOMCSSRuleTable, this, propertyName, slot);
 }
 
 Value DOMCSSRule::getValueProperty(ExecState *exec, int token) const
@@ -893,9 +955,9 @@ const ClassInfo CSSRuleConstructor::info = { "CSSRuleConstructor", 0, &CSSRuleCo
 @end
 */
 
-bool CSSRuleConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool CSSRuleConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<CSSRuleConstructor, DOMObject>(exec, p, &CSSRuleConstructorTable, this, result);
+  return getStaticValueSlot<CSSRuleConstructor, DOMObject>(exec, &CSSRuleConstructorTable, this, propertyName, slot);
 }
 
 Value CSSRuleConstructor::getValueProperty(ExecState *, int token) const
@@ -939,18 +1001,23 @@ DOMCSSValue::~DOMCSSValue()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMCSSValue::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMCSSValue::getValueProperty(ExecState *exec, int token) const
 {
   CSSValueImpl &cssValue = *m_impl;
-  if (p == "cssText") {
-    result = getStringOrNull(cssValue.cssText());
-    return true;
-  } else if (p == "cssValueType"); {
-    result = Number(cssValue.cssValueType());
-    return true;
+  switch (token) {
+  case CssText:
+    return getStringOrNull(cssValue.cssText());
+  case CssValueType:
+    return Number(cssValue.cssValueType());
+  default:
+    assert(0);
+    return Undefined();
   }
+}
 
-  return DOMObject::getOwnProperty(exec, p, result);
+bool DOMCSSValue::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  return getStaticValueSlot<DOMCSSValue, DOMObject>(exec, &DOMCSSValueTable, this, propertyName, slot);
 }
 
 void DOMCSSValue::put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
@@ -993,9 +1060,9 @@ const ClassInfo CSSValueConstructor::info = { "CSSValueConstructor", 0, &CSSValu
   CSS_CUSTOM           CSSValueConstructor::CSS_CUSTOM                 DontDelete|ReadOnly
 @end
 */
-bool CSSValueConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool CSSValueConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<CSSValueConstructor, DOMObject>(exec, p, &CSSValueConstructorTable, this, result);
+  return getStaticValueSlot<CSSValueConstructor, DOMObject>(exec, &CSSValueConstructorTable, this, propertyName, slot);
 }
 
 Value CSSValueConstructor::getValueProperty(ExecState *, int token) const
@@ -1045,14 +1112,15 @@ DOMCSSPrimitiveValue::DOMCSSPrimitiveValue(ExecState *exec, CSSPrimitiveValueImp
   setPrototype(DOMCSSPrimitiveValueProto::self(exec));
 }
 
-bool DOMCSSPrimitiveValue::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMCSSPrimitiveValue::getValueProperty(ExecState *exec, int token)
 {
-  if (p == "primitiveType") {
-    result = Number(static_cast<CSSPrimitiveValueImpl *>(impl())->primitiveType());
-    return result;
-  }
+  assert(token == PrimitiveType);
+  return Number(static_cast<CSSPrimitiveValueImpl *>(impl())->primitiveType());
+}
 
-  return DOMObject::getOwnProperty(exec, p, result);
+bool DOMCSSPrimitiveValue::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  return getStaticValueSlot<DOMCSSPrimitiveValue, DOMCSSValue>(exec, &DOMCSSPrimitiveValueTable, this, propertyName, slot);
 }
 
 Value DOMCSSPrimitiveValueProtoFunc::call(ExecState *exec, Object &thisObj, const List &args)
@@ -1121,9 +1189,9 @@ const ClassInfo CSSPrimitiveValueConstructor::info = { "CSSPrimitiveValueConstru
 @end
 */
 
-bool CSSPrimitiveValueConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool CSSPrimitiveValueConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<CSSPrimitiveValueConstructor, CSSValueConstructor>(exec, p, &CSSPrimitiveValueConstructorTable, this, result);
+  return getStaticValueSlot<CSSPrimitiveValueConstructor, CSSValueConstructor>(exec, &CSSPrimitiveValueConstructorTable, this, propertyName, slot);
 }
 
 Value CSSPrimitiveValueConstructor::getValueProperty(ExecState *, int token) const
@@ -1154,26 +1222,37 @@ DOMCSSValueList::DOMCSSValueList(ExecState *exec, CSSValueListImpl *v)
 { 
 }
 
-bool DOMCSSValueList::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMCSSValueList::getValueProperty(ExecState *exec, int token) const
 {
-  CSSValueListImpl &valueList = *static_cast<CSSValueListImpl *>(impl());
+  assert(token == Length);
+  return Number(static_cast<CSSValueListImpl *>(impl())->length());
+}
 
-  if (p == lengthPropertyName) {
-    result = Number(valueList.length());
-    return true;
-  } else if (p == "item") {
-    result = lookupOrCreateFunction<DOMCSSValueListFunc>(exec,p,this,DOMCSSValueList::Item,1,DontDelete|Function);
-    return true;
+Value DOMCSSValueList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMCSSValueList *thisObj = static_cast<DOMCSSValueList *>(slot.slotBase());
+  return getDOMCSSValue(exec, static_cast<CSSValueListImpl *>(thisObj->impl())->item(slot.index()));
+}
+
+bool DOMCSSValueList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  CSSValueListImpl &valueList = *static_cast<CSSValueListImpl *>(impl());
+  const HashEntry* entry = Lookup::findEntry(&DOMCSSValueListTable, propertyName);
+  if (entry) {
+    if (entry->attr & Function)
+      slot.setStaticEntry(this, entry, staticFunctionGetter<DOMCSSValueListFunc>);
+    else
+      slot.setStaticEntry(this, entry, staticValueGetter<DOMCSSValueList>);
   }
 
   bool ok;
-  long unsigned int u = p.toULong(&ok);
-  if (ok) {
-    result = getDOMCSSValue(exec,valueList.item(u));
+  long unsigned int u = propertyName.toULong(&ok);
+  if (ok && u < valueList.length()) {
+    slot.setCustomIndex(this, u, indexGetter);
     return true;
   }
 
-  return DOMCSSValue::getOwnProperty(exec, p, result);
+  return DOMCSSValue::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 Value DOMCSSValueListFunc::call(ExecState *exec, Object &thisObj, const List &args)
@@ -1208,9 +1287,9 @@ DOMRGBColor::~DOMRGBColor()
   //rgbColors.remove(rgbColor.handle());
 }
 
-bool DOMRGBColor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMRGBColor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMRGBColor, DOMObject>(exec, p, &DOMRGBColorTable, this, result);
+  return getStaticValueSlot<DOMRGBColor, DOMObject>(exec, &DOMRGBColorTable, this, propertyName, slot);
 }
 
 Value DOMRGBColor::getValueProperty(ExecState *exec, int token) const
@@ -1252,9 +1331,9 @@ DOMRect::~DOMRect()
   ScriptInterpreter::forgetDOMObject(m_rect.get());
 }
 
-bool DOMRect::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMRect::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMRect, DOMObject>(exec, p, &DOMRectTable, this, result);
+  return getStaticValueSlot<DOMRect, DOMObject>(exec,  &DOMRectTable, this, propertyName, slot);
 }
 
 Value DOMRect::getValueProperty(ExecState *exec, int token) const
@@ -1295,9 +1374,9 @@ DOMCounter::~DOMCounter()
   ScriptInterpreter::forgetDOMObject(m_counter.get());
 }
 
-bool DOMCounter::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMCounter::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMCounter, DOMObject>(exec, p, &DOMCounterTable, this, result);
+  return getStaticValueSlot<DOMCounter, DOMObject>(exec, &DOMCounterTable, this, propertyName, slot);
 }
 
 Value DOMCounter::getValueProperty(ExecState *, int token) const
index 6b1b0c3..754d809 100644 (file)
@@ -49,16 +49,20 @@ namespace KJS {
   public:
     DOMCSSStyleDeclaration(ExecState *exec, DOM::CSSStyleDeclarationImpl *s);
     virtual ~DOMCSSStyleDeclaration();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
+    Value getValueProperty(ExecState *exec, int token);
+
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
-    enum { CssText, Length, ParentRule,
-           GetPropertyValue, GetPropertyCSSValue, RemoveProperty, GetPropertyPriority,
-           SetProperty, Item };
+    enum { CssText, Length, ParentRule };
+    enum { GetPropertyValue, GetPropertyCSSValue, RemoveProperty, 
+           GetPropertyPriority, SetProperty, Item };
     DOM::CSSStyleDeclarationImpl *impl() const { return m_impl.get(); }
   private:
+    static Value indexGetter(ExecState *, const Identifier&, const PropertySlot&);
+    static Value cssPropertyGetter(ExecState *, const Identifier&, const PropertySlot&);
+
     khtml::SharedPtr<DOM::CSSStyleDeclarationImpl> m_impl;
   };
 
@@ -68,7 +72,7 @@ namespace KJS {
   public:
     DOMStyleSheet(ExecState *, DOM::StyleSheetImpl *ss) : m_impl(ss) { }
     virtual ~DOMStyleSheet();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     virtual bool toBoolean(ExecState *) const { return true; }
@@ -90,7 +94,8 @@ namespace KJS {
     DOMStyleSheetList(ExecState *, DOM::StyleSheetListImpl *ssl, DOM::DocumentImpl *doc)
       : m_impl(ssl), m_doc(doc) { }
     virtual ~DOMStyleSheetList();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     virtual bool toBoolean(ExecState* ) const { return true; }
@@ -98,6 +103,9 @@ namespace KJS {
     DOM::StyleSheetListImpl *impl() const { return m_impl.get(); }
     enum { Item, Length };
   private:
+    static Value indexGetter(ExecState *, const Identifier&, const PropertySlot&);
+    static Value nameGetter(ExecState *, const Identifier&, const PropertySlot&);
+
     khtml::SharedPtr<DOM::StyleSheetListImpl> m_impl;
     khtml::SharedPtr<DOM::DocumentImpl> m_doc;
   };
@@ -109,7 +117,8 @@ namespace KJS {
   public:
     DOMMediaList(ExecState *, DOM::MediaListImpl *ml);
     virtual ~DOMMediaList();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     virtual const ClassInfo* classInfo() const { return &info; }
     virtual bool toBoolean(ExecState* ) const { return true; }
@@ -118,6 +127,7 @@ namespace KJS {
            Item, DeleteMedium, AppendMedium };
     DOM::MediaListImpl *impl() const { return m_impl.get(); }
   private:
+    static Value indexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
     khtml::SharedPtr<DOM::MediaListImpl> m_impl;
   };
 
@@ -127,25 +137,28 @@ namespace KJS {
   public:
     DOMCSSStyleSheet(ExecState *exec, DOM::CSSStyleSheetImpl *ss);
     virtual ~DOMCSSStyleSheet();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
-    enum { OwnerRule, CssRules, Rules,
-           InsertRule, DeleteRule, AddRule };
+    enum { OwnerRule, CssRules, Rules, InsertRule, DeleteRule, AddRule };
   };
 
   class DOMCSSRuleList : public DOMObject {
   public:
     DOMCSSRuleList(ExecState *, DOM::CSSRuleListImpl *rl) : m_impl(rl) { }
     virtual ~DOMCSSRuleList();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
     enum { Item, Length };
     DOM::CSSRuleListImpl *impl() const { return m_impl.get(); }
   private:
+    static Value indexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+
     khtml::SharedPtr<DOM::CSSRuleListImpl> m_impl;
   };
 
@@ -155,15 +168,14 @@ namespace KJS {
   public:
     DOMCSSRule(ExecState *, DOM::CSSRuleImpl *r) : m_impl(r) { }
     virtual ~DOMCSSRule();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int attr);
     virtual const ClassInfo* classInfo() const;
     static const ClassInfo info;
     static const ClassInfo style_info, media_info, fontface_info, page_info, import_info, charset_info;
-    enum { ParentStyleSheet, Type, CssText, ParentRule,
-           Style_SelectorText, Style_Style,
+    enum { ParentStyleSheet, Type, CssText, ParentRule, Style_SelectorText, Style_Style,
            Media_Media, Media_InsertRule, Media_DeleteRule, Media_CssRules,
            FontFace_Style, Page_SelectorText, Page_Style,
            Import_Href, Import_Media, Import_StyleSheet, Charset_Encoding };
@@ -178,7 +190,7 @@ namespace KJS {
   class CSSRuleConstructor : public DOMObject {
   public:
     CSSRuleConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -192,7 +204,8 @@ namespace KJS {
   public:
     DOMCSSValue(ExecState *, DOM::CSSValueImpl *v) : m_impl(v) { }
     virtual ~DOMCSSValue();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
@@ -211,7 +224,7 @@ namespace KJS {
   class CSSValueConstructor : public DOMObject {
   public:
     CSSValueConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -224,7 +237,8 @@ namespace KJS {
   class DOMCSSPrimitiveValue : public DOMCSSValue {
   public:
     DOMCSSPrimitiveValue(ExecState *exec, DOM::CSSPrimitiveValueImpl *v);
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token);
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
@@ -236,7 +250,7 @@ namespace KJS {
   class CSSPrimitiveValueConstructor : public CSSValueConstructor {
   public:
     CSSPrimitiveValueConstructor(ExecState *exec) : CSSValueConstructor(exec) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -248,18 +262,21 @@ namespace KJS {
   class DOMCSSValueList : public DOMCSSValue {
   public:
     DOMCSSValueList(ExecState *exec, DOM::CSSValueListImpl *l);
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
-    enum { Item, Length };
+    enum { Length, Item };
+  private:
+    static Value indexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
   };
 
   class DOMRGBColor : public DOMObject {
   public:
     DOMRGBColor(unsigned color) : m_color(color) { }
     ~DOMRGBColor();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -275,7 +292,7 @@ namespace KJS {
   public:
     DOMRect(ExecState *, DOM::RectImpl *r) : m_rect(r) { }
     ~DOMRect();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -291,7 +308,7 @@ namespace KJS {
   public:
     DOMCounter(ExecState *, DOM::CounterImpl *c) : m_counter(c) { }
     ~DOMCounter();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
index 1379e2c..8833887 100644 (file)
@@ -271,9 +271,9 @@ bool DOMNode::toBoolean(ExecState *) const
   scrollHeight  DOMNode::ScrollHeight           DontDelete|ReadOnly
 @end
 */
-bool DOMNode::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMNode::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMNode, DOMObject>(exec, propertyName, &DOMNodeTable, this, result);
+  return getStaticValueSlot<DOMNode, DOMObject>(exec, &DOMNodeTable, this, propertyName, slot);
 }
 
 Value DOMNode::getValueProperty(ExecState *exec, int token) const
@@ -704,7 +704,14 @@ NodeImpl *toNode(ValueImp *val)
 
 // -------------------------------------------------------------------------
 
-const ClassInfo DOMNodeList::info = { "NodeList", 0, 0, 0 };
+/*
+@begin DOMNodeListTable 2
+  length       DOMStyleSheetList::Length       DontDelete|ReadOnly
+  item         DOMStyleSheetList::Item         DontDelete|Function 1
+@end
+*/
+
+const ClassInfo DOMNodeList::info = { "NodeList", 0, &DOMNodeListTable, 0 };
 
 DOMNodeList::~DOMNodeList()
 {
@@ -719,46 +726,52 @@ Value DOMNodeList::toPrimitive(ExecState *exec, Type /*preferred*/) const
   return String(toString(exec));
 }
 
+Value DOMNodeList::getValueProperty(ExecState *exec, int token) const
+{
+  assert(token == Length);
+  return Number(m_impl->length());
+}
 
+Value DOMNodeList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
+  return getDOMNode(exec, thisObj->m_impl->item(slot.index()));
+}
 
-// We have to implement hasProperty since we don't use a hashtable for 'length' and 'item'
-// ## this breaks "for (..in..)" though.
-bool DOMNodeList::hasOwnProperty(ExecState *exec, const Identifier &p) const
+Value DOMNodeList::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
 {
-  if (p == lengthPropertyName || p == "item")
-    return true;
-  return ObjectImp::hasOwnProperty(exec, p);
+  DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
+  return getDOMNode(exec, thisObj->m_impl->itemById(propertyName.string()));
 }
 
-bool DOMNodeList::getOwnProperty(ExecState *exec, const Identifier &p, Value& result) const
+bool DOMNodeList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  NodeListImpl &list = *m_impl;
-  if (p == lengthPropertyName) {
-    result = Number(list.length());
+  const HashEntry* entry = Lookup::findEntry(&DOMNodeListTable, propertyName);
+
+  if (entry) {
+    if (entry->attr & Function)
+      slot.setStaticEntry(this, entry, staticFunctionGetter<DOMNodeListFunc>);
+    else
+      slot.setStaticEntry(this, entry, staticValueGetter<DOMNodeList>);
     return true;
-  } else if (p == "item") {
-    // No need for a complete hashtable for a single func, but we still want
-    // to use the caching feature of lookupOrCreateFunction.
-    result = lookupOrCreateFunction<DOMNodeListFunc>(exec, p, this, DOMNodeListFunc::Item, 1, DontDelete|Function);
+  }
+
+  NodeListImpl &list = *m_impl;
+
+  // array index ?
+  bool ok;
+  long unsigned int idx = propertyName.toULong(&ok);
+  if (ok && idx < list.length()) {
+    slot.setCustomIndex(this, idx, indexGetter);
     return true;
   } else {
-    // array index ?
-    bool ok;
-    long unsigned int idx = p.toULong(&ok);
-    if (ok) {
-      result = getDOMNode(exec,list.item(idx));
+    if (list.itemById(propertyName.string())) {
+      slot.setCustom(this, nameGetter);
       return true;
-    } else {
-      NodeImpl *node = list.itemById(p.string());
-
-      if (node) {
-        result = getDOMNode(exec, node);
-        return true;
-      } 
     }
   }
 
-  return DOMNodeList::getOwnProperty(exec, p, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 // Need to support both get and call, so that list[0] and list(0) work.
@@ -771,7 +784,6 @@ Value DOMNodeList::call(ExecState *exec, Object &, const List &args)
   if (ok)
     return getDOMNode(exec, m_impl->item(u));
 
-  kdWarning() << "KJS::DOMNodeList::call " << s.qstring() << " not implemented" << endl;
   return Undefined();
 }
 
@@ -816,9 +828,9 @@ DOMAttr::DOMAttr(ExecState *exec, AttrImpl *a)
 {
 }
 
-bool DOMAttr::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMAttr::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMAttr, DOMNode>(exec, propertyName, &DOMAttrTable, this, result);
+  return getStaticValueSlot<DOMAttr, DOMNode>(exec, &DOMAttrTable, this, propertyName, slot);
 }
 
 Value DOMAttr::getValueProperty(ExecState *exec, int token) const
@@ -932,9 +944,9 @@ DOMDocument::~DOMDocument()
   ScriptInterpreter::forgetDOMObject(static_cast<DocumentImpl *>(m_impl.get()));
 }
 
-bool DOMDocument::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMDocument::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMDocument, DOMNode>(exec, propertyName, &DOMDocumentTable, this, result);
+  return getStaticValueSlot<DOMDocument, DOMNode>(exec, &DOMDocumentTable, this, propertyName, slot);
 }
 
 Value DOMDocument::getValueProperty(ExecState *exec, int token) const
@@ -1146,38 +1158,54 @@ DOMElement::DOMElement(ElementImpl *e)
 { 
 }
 
-bool DOMElement::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value DOMElement::getValueProperty(ExecState *exec, int token) const
 {
-  ElementImpl &element = *static_cast<ElementImpl *>(impl());
+  ElementImpl *element = static_cast<ElementImpl *>(impl());
+  switch (token) {
+  case TagName:
+    return getStringOrNull(element->nodeName());
+  case Style:
+    return getDOMCSSStyleDeclaration(exec, element->style());
+  default:
+    assert(0);
+    return Undefined();
+  }
+}
 
+Value DOMElement::attributeGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMElement *thisObj = static_cast<DOMElement *>(slot.slotBase());
+
+  ElementImpl *element = static_cast<ElementImpl *>(thisObj->impl());
+  DOM::DOMString attr = element->getAttribute(propertyName.string());
+  return getStringOrNull(attr);
+}
+
+bool DOMElement::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
   const HashEntry* entry = Lookup::findEntry(&DOMElementTable, propertyName);
-  if (entry)
-  {
-    switch (entry->value) {
-    case TagName:
-      result = getStringOrNull(element.nodeName());
-      break;
-    case Style:
-      result = getDOMCSSStyleDeclaration(exec,element.style());
-      break;
-    default:
-      assert(0);
-    }
+  if (entry) {
+    slot.setStaticEntry(this, entry, staticValueGetter<DOMElement>);
     return true;
   }
+
   // We have to check in DOMNode before giving access to attributes, otherwise
   // onload="..." would make onload return the string (attribute value) instead of
   // the listener object (function).
+  if (DOMNode::getOwnPropertySlot(exec, propertyName, slot))
+    return true;
+
   ValueImp *proto = prototype().imp();
-  if (DOMNode::hasOwnProperty(exec, propertyName))
-    return DOMNode::getOwnProperty(exec, propertyName, result);
   if (proto->dispatchType() == ObjectType && static_cast<ObjectImp *>(proto)->hasProperty(exec, propertyName))
     return false;
 
+  ElementImpl &element = *static_cast<ElementImpl *>(impl());
+
+  // FIXME: do we really want to do this attribute lookup thing? Mozilla doesn't do it,
+  // and it seems like it could interfere with XBL.
   DOM::DOMString attr = element.getAttribute(propertyName.string());
-  // Give access to attributes
   if (!attr.isNull()) {
-    result = getStringOrNull(attr);
+    slot.setCustom(this, attributeGetter);
     return true;
   }
 
@@ -1341,9 +1369,9 @@ const ClassInfo DOMDocumentType::info = { "DocumentType", &DOMNode::info, &DOMDo
 DOMDocumentType::DOMDocumentType(ExecState *exec, DocumentTypeImpl *dt)
   : DOMNode( /*### no proto yet*/exec, dt ) { }
 
-bool DOMDocumentType::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMDocumentType::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMDocumentType, DOMNode>(exec, propertyName, &DOMDocumentTypeTable, this, result);
+  return getStaticValueSlot<DOMDocumentType, DOMNode>(exec, &DOMDocumentTypeTable, this, propertyName, slot);
 }
 
 Value DOMDocumentType::getValueProperty(ExecState *exec, int token) const
@@ -1406,33 +1434,35 @@ DOMNamedNodeMap::~DOMNamedNodeMap()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-// We have to implement hasProperty since we don't use a hashtable for 'length'
-// ## this breaks "for (..in..)" though.
-bool DOMNamedNodeMap::hasOwnProperty(ExecState *exec, const Identifier &p) const
+Value DOMNamedNodeMap::lengthGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
 {
-  if (p == lengthPropertyName)
-    return true;
-  return DOMObject::hasOwnProperty(exec, p);
+  DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
+  return Number(thisObj->m_impl->length());
 }
 
-bool DOMNamedNodeMap::getOwnProperty(ExecState* exec, const Identifier& p, Value& result) const
+Value DOMNamedNodeMap::indexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
+  return getDOMNode(exec, thisObj->m_impl->item(slot.index()));
+}
+
+bool DOMNamedNodeMap::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
   NamedNodeMapImpl &map = *m_impl;
-  if (p == lengthPropertyName) {
-    result = Number(map.length());
+  if (propertyName == lengthPropertyName) {
+    slot.setCustom(this, lengthGetter);
     return true;
   }
 
   // array index ?
   bool ok;
-  long unsigned int idx = p.toULong(&ok);
-  if (ok) {
-    result = getDOMNode(exec,map.item(idx));
+  long unsigned int idx = propertyName.toULong(&ok);
+  if (ok && idx < map.length()) {
+    slot.setCustomIndex(this, idx, indexGetter);
     return true;
   }
 
-  // Anything else (including functions, defined in the prototype)
-  return DOMObject::getOwnProperty(exec, p, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 Value DOMNamedNodeMapProtoFunc::call(ExecState *exec, Object &thisObj, const List &args)
@@ -1484,9 +1514,9 @@ DOMProcessingInstruction::DOMProcessingInstruction(ExecState *exec, ProcessingIn
 {
 }
 
-bool DOMProcessingInstruction::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMProcessingInstruction::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMProcessingInstruction, DOMNode>(exec, propertyName, &DOMProcessingInstructionTable, this, result);
+  return getStaticValueSlot<DOMProcessingInstruction, DOMNode>(exec, &DOMProcessingInstructionTable, this, propertyName, slot);
 }
 
 Value DOMProcessingInstruction::getValueProperty(ExecState *exec, int token) const
@@ -1532,9 +1562,9 @@ DOMNotation::DOMNotation(ExecState *exec, NotationImpl *n)
 {
 }
 
-bool DOMNotation::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMNotation::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMNotation, DOMNode>(exec, propertyName, &DOMNotationTable, this, result);
+  return getStaticValueSlot<DOMNotation, DOMNode>(exec, &DOMNotationTable, this, propertyName, slot);
 }
 
 Value DOMNotation::getValueProperty(ExecState *, int token) const
@@ -1567,9 +1597,9 @@ DOMEntity::DOMEntity(ExecState *exec, EntityImpl *e)
 {
 }
 
-bool DOMEntity::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMEntity::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMEntity, DOMNode>(exec, propertyName, &DOMEntityTable, this, result);
+  return getStaticValueSlot<DOMEntity, DOMNode>(exec, &DOMEntityTable, this, propertyName, slot);
 }
 
 Value DOMEntity::getValueProperty(ExecState *, int token) const
@@ -1741,9 +1771,9 @@ const ClassInfo NodeConstructor::info = { "NodeConstructor", 0, &NodeConstructor
   NOTATION_NODE                DOM::Node::NOTATION_NODE                DontDelete|ReadOnly
 @end
 */
-bool NodeConstructor::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool NodeConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<NodeConstructor, DOMObject>(exec, propertyName, &NodeConstructorTable, this, result);
+  return getStaticValueSlot<NodeConstructor, DOMObject>(exec, &NodeConstructorTable, this, propertyName, slot);
 }
 
 Value NodeConstructor::getValueProperty(ExecState *, int token) const
@@ -1812,9 +1842,9 @@ const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0,
 @end
 */
 
-bool DOMExceptionConstructor::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool DOMExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMExceptionConstructor, DOMObject>(exec, propertyName, &DOMExceptionConstructorTable, this, result);
+  return getStaticValueSlot<DOMExceptionConstructor, DOMObject>(exec, &DOMExceptionConstructorTable, this, propertyName, slot);
 }
 
 Value DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
@@ -1875,35 +1905,48 @@ DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *, const QValueList<
 {
 }
 
-bool DOMNamedNodesCollection::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value DOMNamedNodesCollection::lengthGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
+  return Number(thisObj->m_nodes.count());
+}
+
+Value DOMNamedNodesCollection::indexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
+  return getDOMNode(exec, thisObj->m_nodes[slot.index()].get());
+}
+
+bool DOMNamedNodesCollection::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
   if (propertyName == lengthPropertyName) {
-    result = Number(m_nodes.count());
+    slot.setCustom(this, lengthGetter);
     return true;
   }
-  // index?
+
+  // array index ?
   bool ok;
-  unsigned int u = propertyName.toULong(&ok);
-  if (ok && u < m_nodes.count()) {
-    result = getDOMNode(exec, m_nodes[u].get());
+  long unsigned int idx = propertyName.toULong(&ok);
+  if (ok && idx < m_nodes.count()) {
+    slot.setCustomIndex(this, idx, indexGetter);
     return true;
   }
+
   // For IE compatibility, we need to be able to look up elements in a
   // document.formName.name result by id as well as be index.
 
-  if (!ok) {
-    QValueListConstIterator< SharedPtr<NodeImpl> > end = m_nodes.end();
-    for (QValueListConstIterator< SharedPtr<NodeImpl> > it = m_nodes.begin(); it != end; it++) {
-      NodeImpl *node = (*it).get();
-      if (node->hasAttributes() &&
-          node->attributes()->id() == propertyName.string()) {
-       result = getDOMNode(exec,node);
-        return true;
-      }
+  QValueListConstIterator< SharedPtr<NodeImpl> > end = m_nodes.end();
+  int i = 0;
+  for (QValueListConstIterator< SharedPtr<NodeImpl> > it = m_nodes.begin(); it != end; ++it, ++i) {
+    NodeImpl *node = (*it).get();
+    if (node->hasAttributes() &&
+        node->attributes()->id() == propertyName.string()) {
+      slot.setCustomIndex(this, i, indexGetter);
+      return true;
     }
   }
 
-  return DOMObject::getOwnProperty(exec, propertyName, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 // -------------------------------------------------------------------------
@@ -1938,9 +1981,9 @@ DOMCharacterData::DOMCharacterData(CharacterDataImpl *d)
 {
 }
 
-bool DOMCharacterData::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMCharacterData::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMCharacterData, DOMNode>(exec, p, &DOMCharacterDataTable, this, result);
+  return getStaticValueSlot<DOMCharacterData, DOMNode>(exec, &DOMCharacterDataTable, this, propertyName, slot);
 }
 
 Value DOMCharacterData::getValueProperty(ExecState *, int token) const
index d3c63ca..c266c20 100644 (file)
@@ -49,7 +49,7 @@ namespace KJS {
     DOMNode(ExecState *exec, DOM::NodeImpl *n);
     virtual ~DOMNode();
     virtual bool toBoolean(ExecState *) const;
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void mark();
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
@@ -91,8 +91,8 @@ namespace KJS {
   public:
     DOMNodeList(ExecState *, DOM::NodeListImpl *l) : m_impl(l) { }
     ~DOMNodeList();
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &p) const;
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     virtual Value call(ExecState *exec, Object &thisObj, const List&args);
     virtual bool implementsCall() const { return true; }
     // no put - all read-only
@@ -104,6 +104,9 @@ namespace KJS {
     virtual Value toPrimitive(ExecState *exec, Type preferred = UndefinedType) const;
 
   private:
+    static Value indexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value nameGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+
     khtml::SharedPtr<DOM::NodeListImpl> m_impl;
   };
 
@@ -111,7 +114,7 @@ namespace KJS {
   public:
     DOMDocument(ExecState *exec, DOM::DocumentImpl *d);
     ~DOMDocument();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int attr);
@@ -137,7 +140,7 @@ namespace KJS {
   class DOMAttr : public DOMNode {
   public:
     DOMAttr(ExecState *exec, DOM::AttrImpl *a);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     Value getValueProperty(ExecState *exec, int token) const;
     void putValueProperty(ExecState *exec, int token, const Value& value, int attr);
@@ -151,7 +154,8 @@ namespace KJS {
   class DOMElement : public DOMNode {
   public:
     DOMElement(ExecState *exec, DOM::ElementImpl *e);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
@@ -164,6 +168,8 @@ namespace KJS {
   protected:
     // Constructor for inherited classes; doesn't set up a prototype.
     DOMElement(DOM::ElementImpl *e);
+  private:
+    static Value attributeGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
   };
 
   DOM::ElementImpl *toElement(ValueImp *); // returns 0 if passed-in value is not a DOMElement object
@@ -186,7 +192,7 @@ namespace KJS {
   class DOMDocumentType : public DOMNode {
   public:
     DOMDocumentType(ExecState *exec, DOM::DocumentTypeImpl *dt);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -200,8 +206,7 @@ namespace KJS {
   public:
     DOMNamedNodeMap(ExecState *, DOM::NamedNodeMapImpl *m);
     ~DOMNamedNodeMap();
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &p) const;
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     virtual bool toBoolean(ExecState *) const { return true; }
@@ -210,13 +215,16 @@ namespace KJS {
            GetNamedItemNS, SetNamedItemNS, RemoveNamedItemNS };
     DOM::NamedNodeMapImpl *impl() const { return m_impl.get(); }
   private:
+    static Value lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot);
+    static Value indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot);
+
     khtml::SharedPtr<DOM::NamedNodeMapImpl> m_impl;
   };
 
   class DOMProcessingInstruction : public DOMNode {
   public:
     DOMProcessingInstruction(ExecState *exec, DOM::ProcessingInstructionImpl *pi);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -227,7 +235,7 @@ namespace KJS {
   class DOMNotation : public DOMNode {
   public:
     DOMNotation(ExecState *exec, DOM::NotationImpl *n);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -238,7 +246,7 @@ namespace KJS {
   class DOMEntity : public DOMNode {
   public:
     DOMEntity(ExecState *exec, DOM::EntityImpl *e);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -250,7 +258,7 @@ namespace KJS {
   class NodeConstructor : public DOMObject {
   public:
     NodeConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -261,7 +269,7 @@ namespace KJS {
   class DOMExceptionConstructor : public DOMObject {
   public:
     DOMExceptionConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -283,15 +291,18 @@ namespace KJS {
   class DOMNamedNodesCollection : public DOMObject {
   public:
     DOMNamedNodesCollection(ExecState *exec, const QValueList< khtml::SharedPtr<DOM::NodeImpl> >& nodes );
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
   private:
+    static Value lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot);
+    static Value indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot);
+
     QValueList< khtml::SharedPtr<DOM::NodeImpl> > m_nodes;
   };
 
   class DOMCharacterData : public DOMNode {
   public:
     DOMCharacterData(ExecState *exec, DOM::CharacterDataImpl *d);
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     virtual const ClassInfo* classInfo() const { return &info; }
index c12cbf0..3bbfd1c 100644 (file)
@@ -351,9 +351,9 @@ const ClassInfo EventConstructor::info = { "EventConstructor", 0, &EventConstruc
 @end
 */
 
-bool EventConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool EventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<EventConstructor, DOMObject>(exec, p, &EventConstructorTable, this, result);
+  return getStaticValueSlot<EventConstructor, DOMObject>(exec, &EventConstructorTable, this, propertyName, slot);
 }
 
 Value EventConstructor::getValueProperty(ExecState *, int token) const
@@ -414,9 +414,9 @@ void DOMMouseEvent::mark()
         clipboard->mark();
 }
 
-bool DOMEvent::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMEvent, DOMObject>(exec, p, &DOMEventTable, this, result);
+  return getStaticValueSlot<DOMEvent, DOMObject>(exec, &DOMEventTable, this, propertyName, slot);
 }
 
 Value DOMEvent::getValueProperty(ExecState *exec, int token) const
@@ -562,9 +562,9 @@ const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor",
   UNSPECIFIED_EVENT_TYPE_ERR    DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
 @end
 */
-bool EventExceptionConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool EventExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<EventExceptionConstructor, DOMObject>(exec, p, &EventExceptionConstructorTable, this, result);
+  return getStaticValueSlot<EventExceptionConstructor, DOMObject>(exec, &EventExceptionConstructorTable, this, propertyName, slot);
 }
 
 Value EventExceptionConstructor::getValueProperty(ExecState *, int token) const
@@ -611,9 +611,9 @@ DOMUIEvent::~DOMUIEvent()
 {
 }
 
-bool DOMUIEvent::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMUIEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMUIEvent,DOMEvent>(exec, p, &DOMUIEventTable, this, result);
+  return getStaticValueSlot<DOMUIEvent, DOMEvent>(exec, &DOMUIEventTable, this, propertyName, slot);
 }
 
 Value DOMUIEvent::getValueProperty(ExecState *exec, int token) const
@@ -705,9 +705,9 @@ DOMMouseEvent::~DOMMouseEvent()
 {
 }
 
-bool DOMMouseEvent::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMMouseEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMMouseEvent, DOMUIEvent>(exec, p, &DOMMouseEventTable, this, result);
+  return getStaticValueSlot<DOMMouseEvent, DOMUIEvent>(exec, &DOMMouseEventTable, this, propertyName, slot);
 }
 
 static QPoint offsetFromTarget(const MouseRelatedEventImpl *e)
@@ -853,9 +853,9 @@ const ClassInfo* DOMKeyboardEvent::classInfo() const
     return &info;
 }
 
-bool DOMKeyboardEvent::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMKeyboardEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMKeyboardEvent, DOMUIEvent>(exec, p, &DOMKeyboardEventTable, this, result);
+  return getStaticValueSlot<DOMKeyboardEvent, DOMUIEvent>(exec, &DOMKeyboardEventTable, this, propertyName, slot);
 }
 
 Value DOMKeyboardEvent::getValueProperty(ExecState *exec, int token) const
@@ -918,9 +918,9 @@ const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", 0
   REMOVAL      DOM::MutationEvent::REMOVAL             DontDelete|ReadOnly
 @end
 */
-bool MutationEventConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool MutationEventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<MutationEventConstructor,DOMObject>(exec, p, &MutationEventConstructorTable, this, result);
+  return getStaticValueSlot<MutationEventConstructor, DOMObject>(exec, &MutationEventConstructorTable, this, propertyName, slot);
 }
 
 Value MutationEventConstructor::getValueProperty(ExecState *, int token) const
@@ -963,9 +963,9 @@ DOMMutationEvent::~DOMMutationEvent()
 {
 }
 
-bool DOMMutationEvent::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMMutationEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMMutationEvent, DOMEvent>(exec, p, &DOMMutationEventTable, this, result);
+  return getStaticValueSlot<DOMMutationEvent, DOMEvent>(exec, &DOMMutationEventTable, this, propertyName, slot);
 }
 
 Value DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
@@ -1042,9 +1042,9 @@ DOMWheelEvent::DOMWheelEvent(ExecState *exec, DOM::WheelEventImpl *e)
 {
 }
 
-bool DOMWheelEvent::getOwnProperty(ExecState *exec, const Identifier &p, Value& result) const
+bool DOMWheelEvent::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    return lookupGetOwnValue<DOMWheelEvent,DOMEvent>(exec, p, &DOMWheelEventTable, this, result);
+    return getStaticValueSlot<DOMWheelEvent, DOMEvent>(exec, &DOMWheelEventTable, this, propertyName, slot);
 }
 
 Value DOMWheelEvent::getValueProperty(ExecState *exec, int token) const
@@ -1135,9 +1135,9 @@ static Value stringOrUndefined(const DOM::DOMString &str)
     }
 }
 
-bool Clipboard::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool Clipboard::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    return lookupGetOwnValue<Clipboard, DOMObject>(exec, propertyName, &ClipboardTable, this, result);
+    return getStaticValueSlot<Clipboard, DOMObject>(exec, &ClipboardTable, this, propertyName, slot);
 }
 
 Value Clipboard::getValueProperty(ExecState *exec, int token) const
index a6a038e..88d64fd 100644 (file)
@@ -99,7 +99,7 @@ namespace KJS {
   class EventConstructor : public DOMObject {
   public:
     EventConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -112,7 +112,7 @@ namespace KJS {
   public:
     DOMEvent(ExecState *exec, DOM::EventImpl *e);
     ~DOMEvent();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName,
                        const Value& value, int attr = None);
@@ -137,7 +137,7 @@ namespace KJS {
   class EventExceptionConstructor : public DOMObject {
   public:
     EventExceptionConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -150,7 +150,7 @@ namespace KJS {
   public:
     DOMUIEvent(ExecState *exec, DOM::UIEventImpl *ue);
     ~DOMUIEvent();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -162,7 +162,7 @@ namespace KJS {
   public:
     DOMMouseEvent(ExecState *exec, DOM::MouseEventImpl *me);
     ~DOMMouseEvent();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     virtual void mark();
     // no put - all read-only
@@ -178,7 +178,7 @@ namespace KJS {
   public:
     DOMKeyboardEvent(ExecState *exec, DOM::KeyboardEventImpl *ke);
     ~DOMKeyboardEvent();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const;
@@ -190,7 +190,7 @@ namespace KJS {
   class MutationEventConstructor : public DOMObject {
   public:
     MutationEventConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -203,7 +203,7 @@ namespace KJS {
   public:
     DOMMutationEvent(ExecState *exec, DOM::MutationEventImpl *me);
     ~DOMMutationEvent();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -215,7 +215,7 @@ namespace KJS {
     class DOMWheelEvent : public DOMUIEvent {
     public:
         DOMWheelEvent(ExecState *, DOM::WheelEventImpl *);
-        virtual bool getOwnProperty(ExecState *, const Identifier &p, Value& result) const;
+        virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
         Value getValueProperty(ExecState *, int token) const;
         // no put - all read-only
         virtual const ClassInfo* classInfo() const { return &info; }
@@ -229,7 +229,7 @@ namespace KJS {
   public:
     Clipboard(ExecState *exec, DOM::ClipboardImpl *ds);
     ~Clipboard();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
index 7791cc2..9f7351d 100644 (file)
@@ -1,4 +1,4 @@
-// -*- c-basic-offset: 2 -*-
+// -*- c-basic-offset: 4 -*-
 /*
  *  This file is part of the KDE libraries
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
@@ -269,173 +269,141 @@ HTMLDocument::HTMLDocument(ExecState *exec, HTMLDocumentImpl *d)
 {
 }
 
-bool HTMLDocument::hasOwnProperty(ExecState *exec, const Identifier &p) const
+Value HTMLDocument::namedItemGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
 {
-#ifdef KJS_VERBOSE
-  //kdDebug(6070) << "HTMLDocument::hasProperty " << p.qstring() << endl;
-#endif
-  if (DOMDocument::hasOwnProperty(exec, p))
-    return true;
+  HTMLDocument *thisObj = static_cast<HTMLDocument *>(slot.slotBase());
+  HTMLDocumentImpl &doc = *static_cast<HTMLDocumentImpl *>(thisObj->impl());
 
-  HTMLDocumentImpl *doc = static_cast<HTMLDocumentImpl *>(impl());
-  DOMString name = p.string();
-  return doc->hasNamedItem(name) || doc->hasDocExtraNamedItem(name);
+  DOMString name = propertyName.string();
+  SharedPtr<DOM::HTMLCollectionImpl> collection = doc.documentNamedItems(name);
+
+  if (collection->length() == 1) {
+    NodeImpl *node = collection->firstItem();
+    KHTMLPart *part;
+    if (node->hasTagName(iframeTag) && 
+        (part = static_cast<DOM::HTMLIFrameElementImpl *>(node)->contentPart()))
+      return Window::retrieve(part);
+
+    return getDOMNode(exec, node);
+  }
+
+  return getHTMLCollection(exec, collection.get());
 }
 
-bool HTMLDocument::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value HTMLDocument::getValueProperty(ExecState *exec, int token) const
 {
   HTMLDocumentImpl &doc = *static_cast<HTMLDocumentImpl *>(impl());
-  HTMLElementImpl *body = doc.body();
 
   KHTMLView *view = doc.view();
   KHTMLPart *part = doc.part();
 
-  DOMString name = propertyName.string();
-  if (doc.hasNamedItem(name) || doc.hasDocExtraNamedItem(name)) {
-    SharedPtr<DOM::HTMLCollectionImpl> collection = doc.documentNamedItems(name);
-    if (collection->length() == 1) {
-      NodeImpl *node = collection->firstItem();
-      KHTMLPart *part;
-      if (node->hasTagName(iframeTag) && 
-          (part = static_cast<DOM::HTMLIFrameElementImpl *>(node)->contentPart()))
-        result = Window::retrieve(part);
-      else
-        result = getDOMNode(exec, node);
-    } else 
-      result = getHTMLCollection(exec, collection.get());
-    return true;
-  }
-
+  HTMLElementImpl *body = doc.body();
   HTMLBodyElementImpl *bodyElement = (body && body->hasTagName(bodyTag)) ? static_cast<HTMLBodyElementImpl *>(body) : 0;
     
-  const HashEntry* entry = Lookup::findEntry(&HTMLDocumentTable, propertyName);
-  if (entry) {
-    switch (entry->value) {
-    case Title:
-      result = String(doc.title());
-      return true;
-    case Referrer:
-      result = String(doc.referrer());
-      return true;
-    case Domain:
-      result = String(doc.domain());
-      return true;
-    case URL:
-      result = String(doc.URL());
-      return true;
-    case Body:
-      result = getDOMNode(exec, body);
-      return true;
-    case Location:
-      if (part) {
-        Window* win = Window::retrieveWindow(part);
-        if (win) {
-          result = Value(win->location());
-          return true;
-        }
-      }
-      result = Undefined();
-      return true;
-    case Cookie:
-      result = String(doc.cookie());
-      return true;
-    case Images:
-      result = getHTMLCollection(exec, doc.images().get());
-      return true;
-    case Embeds:
-      result = getHTMLCollection(exec, doc.embeds().get());
-      return true;
-    case Applets:
-      result = getHTMLCollection(exec, doc.applets().get());
-      return true;
-    case Links:
-      result = getHTMLCollection(exec, doc.links().get());
-      return true;
-    case Forms:
-      result = getHTMLCollection(exec, doc.forms().get());
-      return true;
-    case Anchors:
-      result = getHTMLCollection(exec, doc.anchors().get());
-      return true;
-    case Scripts: // TODO (IE-specific)
+  switch (token) {
+  case Title:
+    return String(doc.title());
+  case Referrer:
+    return String(doc.referrer());
+  case Domain:
+    return String(doc.domain());
+  case URL:
+    return String(doc.URL());
+  case Body:
+    return getDOMNode(exec, body);
+  case Location:
+    if (part) {
+      Window* win = Window::retrieveWindow(part);
+      if (win)
+        return Value(win->location());
+    }
+
+    return Undefined();
+  case Cookie:
+    return String(doc.cookie());
+  case Images:
+    return getHTMLCollection(exec, doc.images().get());
+  case Embeds:
+    return getHTMLCollection(exec, doc.embeds().get());
+  case Applets:
+    return getHTMLCollection(exec, doc.applets().get());
+  case Links:
+    return getHTMLCollection(exec, doc.links().get());
+  case Forms:
+    return getHTMLCollection(exec, doc.forms().get());
+  case Anchors:
+    return getHTMLCollection(exec, doc.anchors().get());
+  case Scripts: // TODO (IE-specific)
     {
       // To be implemented. Meanwhile, return an object with a length property set to 0
       kdWarning() << "KJS::HTMLDocument document.scripts called - not implemented" << endl;
       Object obj(new ObjectImp());
       obj.put(exec, lengthPropertyName, Number(0));
-      result = obj;
-      return true;
-    }
-    case All:
-      // Disable document.all when we try to be Netscape-compatible
-      if (exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat)
-        result = Undefined();
-      result = getHTMLCollection(exec, doc.all().get());
-      return true;
-    case Clear:
-    case Open:
-    case Close:
-    case Write:
-    case WriteLn:
-    case GetElementsByName:
-    case CaptureEvents:
-    case ReleaseEvents:
-      result = lookupOrCreateFunction<HTMLDocFunction>( exec, propertyName, this, entry->value, entry->params, entry->attr );
-      return true;
-    case BgColor:
-      if (bodyElement)
-        result = String(bodyElement->bgColor());
-      else
-        result = Undefined();
-      return true;
-    case FgColor:
-      if (bodyElement)
-        result = String(bodyElement->text());
-      else
-        result = Undefined();
-      return true;
-    case AlinkColor:
-      if (bodyElement)
-        result = String(bodyElement->aLink());
-      else
-        result = Undefined();
-      return true;
-    case LinkColor:
-      if (bodyElement)
-        result = String(bodyElement->link());
-      else
-        result = Undefined();
-      return true;
-    case VlinkColor:
-      if (bodyElement)
-        result = String(bodyElement->vLink());
-      else
-        result = Undefined();
-      return true;
-    case LastModified:
-      result = String(doc.lastModified());
-      return true;
-    case Height:
-      result = Number(view ? view->contentsHeight() : 0);
-      return true;
-    case Width:
-      result = Number(view ? view->contentsWidth() : 0);
-      return true;
-    case Dir:
-      if (bodyElement)
-        result = String(bodyElement->dir());
-      else 
-        result = Undefined();
-      return true;
-    case DesignMode:
-      result = String(doc.inDesignMode() ? "on" : "off");
-      return true;
-    default:
-      assert(0);
+      return obj;
     }
+  case All:
+    // Disable document.all when we try to be Netscape-compatible
+    if (exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat)
+      return Undefined();
+    return getHTMLCollection(exec, doc.all().get());
+  case BgColor:
+    if (!bodyElement)
+      return Undefined();
+    return String(bodyElement->bgColor());
+  case FgColor:
+    if (!bodyElement)
+      return Undefined();
+    return String(bodyElement->text());
+  case AlinkColor:
+    if (!bodyElement)
+      return Undefined();
+    return String(bodyElement->aLink());
+  case LinkColor:
+    if (!bodyElement)
+      return Undefined();
+    return String(bodyElement->link());
+  case VlinkColor:
+    if (!bodyElement)
+      return Undefined();
+    return String(bodyElement->vLink());
+  case LastModified:
+    return String(doc.lastModified());
+  case Height:
+    return Number(view ? view->contentsHeight() : 0);
+  case Width:
+    return Number(view ? view->contentsWidth() : 0);
+  case Dir:
+    if (!bodyElement)
+      return Undefined();
+    return String(bodyElement->dir());
+  case DesignMode:
+    return String(doc.inDesignMode() ? "on" : "off");
+  default:
+    assert(0);
+    return Undefined();
+  }
+}
+
+bool HTMLDocument::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+  HTMLDocumentImpl &doc = *static_cast<HTMLDocumentImpl *>(impl());
+
+  DOMString name = propertyName.string();
+  if (doc.hasNamedItem(name) || doc.hasDocExtraNamedItem(name)) {
+    slot.setCustom(this, namedItemGetter);
+    return true;
+  }
+
+  const HashEntry* entry = Lookup::findEntry(&HTMLDocumentTable, propertyName);
+  if (entry) {
+    if (entry->attr & Function)
+      slot.setStaticEntry(this, entry, staticFunctionGetter<HTMLDocFunction>);
+    else 
+      slot.setStaticEntry(this, entry, staticValueGetter<HTMLDocument>);
+    return true;
   }
 
-  return DOMDocument::getOwnProperty(exec, propertyName, result);
+  return DOMDocument::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 void KJS::HTMLDocument::put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
@@ -1300,7 +1268,87 @@ HTMLElement::HTMLElement(ExecState *exec, HTMLElementImpl *e)
 {
 }
 
-bool KJS::HTMLElement::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value HTMLElement::formIndexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLElement *thisObj = static_cast<HTMLElement *>(slot.slotBase());
+    HTMLFormElementImpl *form = static_cast<HTMLFormElementImpl *>(thisObj->impl());
+
+    return getDOMNode(exec, form->elements()->item(slot.index()));
+}
+
+Value HTMLElement::formNameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLElement *thisObj = static_cast<HTMLElement *>(slot.slotBase());
+    HTMLFormElementImpl *form = static_cast<HTMLFormElementImpl *>(thisObj->impl());
+    
+    return HTMLCollection(exec, form->elements().get()).getNamedItems(exec, propertyName);
+}
+
+Value HTMLElement::selectIndexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLElement *thisObj = static_cast<HTMLElement *>(slot.slotBase());
+    HTMLSelectElementImpl *select = static_cast<HTMLSelectElementImpl *>(thisObj->impl());
+
+    return getDOMNode(exec, select->optionsHTMLCollection()->item(slot.index()));
+}
+
+Value HTMLElement::framesetNameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLElement *thisObj = static_cast<HTMLElement *>(slot.slotBase());
+    HTMLElementImpl *element = static_cast<HTMLElementImpl *>(thisObj->impl());
+
+    NodeImpl *frame = element->children()->namedItem(propertyName.string());
+    DocumentImpl* doc = static_cast<HTMLFrameElementImpl *>(frame)->contentDocument();
+    if (doc) {
+        KHTMLPart* part = doc->part();
+        if (part) {
+            Window *window = Window::retrieveWindow(part);
+            if (window) {
+                return Value(window);
+            }
+        }
+    }
+
+    return Undefined();
+}
+
+Value HTMLElement::frameWindowPropertyGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLElement *thisObj = static_cast<HTMLElement *>(slot.slotBase());
+    DocumentImpl *doc = static_cast<HTMLFrameElementImpl *>(thisObj->impl())->contentDocument();
+
+    if (doc) {
+        KHTMLPart* part = doc->part();
+        if (part) {
+            Window *window = Window::retrieveWindow(part);
+            if (window)
+                return window->get(exec, propertyName);
+        }
+    }
+
+    return Undefined();
+}
+
+Value HTMLElement::runtimeObjectGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLElement *thisObj = static_cast<HTMLElement *>(slot.slotBase());
+    HTMLElementImpl *element = static_cast<HTMLElementImpl *>(thisObj->impl());
+
+    return getRuntimeObject(exec, element);
+}
+
+Value HTMLElement::runtimeObjectPropertyGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLElement *thisObj = static_cast<HTMLElement *>(slot.slotBase());
+    HTMLElementImpl *element = static_cast<HTMLElementImpl *>(thisObj->impl());
+
+    Value runtimeObject = getRuntimeObject(exec, element);
+    if (!runtimeObject.isNull())
+        return static_cast<ObjectImp *>(runtimeObject.imp())->get(exec, propertyName);
+    return Undefined();
+}
+
+bool HTMLElement::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
     HTMLElementImpl &element = *static_cast<HTMLElementImpl *>(impl());
 
@@ -1311,51 +1359,38 @@ bool KJS::HTMLElement::getOwnProperty(ExecState *exec, const Identifier& propert
         bool ok;
         uint u = propertyName.toULong(&ok);
         if (ok) {
-            result = getDOMNode(exec, form.elements()->item(u));
+            slot.setCustomIndex(this, u, formIndexGetter);
             return true;
         }
 
+        // FIXME: need faster way to check for a named item and/or a way to pass on the named items subcollection
         ValueImp *namedItems = HTMLCollection(exec, form.elements().get()).getNamedItems(exec, propertyName);
         if (!namedItems->isUndefined()) {
-            result = namedItems;
+            slot.setCustom(this, formNameGetter);
             return true;
         }
-    }
-    else if (element.hasLocalName(selectTag)) {
-        HTMLSelectElementImpl &select = static_cast<HTMLSelectElementImpl &>(element);
+    } else if (element.hasLocalName(selectTag)) {
         bool ok;
         uint u = propertyName.toULong(&ok);
         if (ok) {
             // not specified by DOM(?) but supported in netscape/IE
-            result = getDOMNode(exec, select.optionsHTMLCollection()->item(u));
+            slot.setCustomIndex(this, u, selectIndexGetter);
             return true;
         }
-    }
-    else if (element.hasLocalName(framesetTag)) {
+    } else if (element.hasLocalName(framesetTag)) {
         NodeImpl *frame = element.children()->namedItem(propertyName.string());
         if (frame && frame->hasTagName(frameTag)) {
-            DocumentImpl* doc = static_cast<HTMLFrameElementImpl *>(frame)->contentDocument();
-            if (doc) {
-                KHTMLPart* part = doc->part();
-                if (part) {
-                    Window *window = Window::retrieveWindow(part);
-                    if (window) {
-                        result = Value(window);
-                        return true;
-                    }
-                }
-            }
+            slot.setCustom(this, framesetNameGetter);
         }
-    }
-    else if (element.hasLocalName(frameTag) || element.hasLocalName(iframeTag)) {
+    } else if (element.hasLocalName(frameTag) || element.hasLocalName(iframeTag)) {
         DocumentImpl* doc = static_cast<HTMLFrameElementImpl &>(element).contentDocument();
         if (doc) {
-            KHTMLPart* part = doc->part();
+          KHTMLPart* part = doc->part();
             if (part) {
                 Window *window = Window::retrieveWindow(part);
                 if (window && window->hasProperty(exec, propertyName)) {
-                    result = window->get(exec, propertyName);
-                    return result;
+                    slot.setCustom(this, frameWindowPropertyGetter);
+                    return true;
                 }
             }
         }
@@ -1364,14 +1399,14 @@ bool KJS::HTMLElement::getOwnProperty(ExecState *exec, const Identifier& propert
     else if (element.hasLocalName(embedTag) || element.hasLocalName(objectTag) ||
              element.hasLocalName(appletTag)) {
         if (propertyName == "__apple_runtime_object") {
-           result = getRuntimeObject(exec,&element);
+            slot.setCustom(this, runtimeObjectGetter);
             return true;
         }
        Value runtimeObject = getRuntimeObject(exec,&element);
        if (!runtimeObject.isNull()) {
            ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
            if (imp->hasProperty(exec, propertyName)) {
-               result = imp->get(exec, propertyName);
+                slot.setCustom(this, runtimeObjectPropertyGetter);
                 return true;
             }
        }
@@ -1381,15 +1416,32 @@ bool KJS::HTMLElement::getOwnProperty(ExecState *exec, const Identifier& propert
     const HashTable* table = classInfo()->propHashTable; // get the right hashtable
     const HashEntry* entry = Lookup::findEntry(table, propertyName);
     if (entry) {
-        if (entry->attr & Function)
-            result = lookupOrCreateFunction<KJS::HTMLElementFunction>(exec, propertyName, this, entry->value, entry->params, entry->attr);
-        else
-            result = getValueProperty(exec, entry->value);
-        return true;
+        // don't expose selection properties for input types that can't have a selection
+        if (element.hasLocalName(inputTag) &&
+            !static_cast<HTMLInputElementImpl *>(impl())->canHaveSelection()) {
+            switch (entry->value) {
+            case InputSetSelectionRange:
+            case InputSelectionStart:
+            case InputSelectionEnd:
+                break;
+            default:
+                if (entry->attr & Function)
+                    slot.setStaticEntry(this, entry, staticFunctionGetter<HTMLElementFunction>); 
+                else
+                    slot.setStaticEntry(this, entry, staticValueGetter<HTMLElement>);
+                return true;
+            }
+        } else {
+            if (entry->attr & Function)
+                slot.setStaticEntry(this, entry, staticFunctionGetter<HTMLElementFunction>); 
+            else
+                slot.setStaticEntry(this, entry, staticValueGetter<HTMLElement>);
+            return true;
+        }
     }
 
     // Base HTMLElement stuff or parent class forward, as usual
-    return lookupGetOwnProperty<KJS::HTMLElementFunction, KJS::HTMLElement, DOMElement>(exec, propertyName, &HTMLElementTable, this, result);
+    return getStaticPropertySlot<HTMLElementFunction, HTMLElement, DOMElement>(exec, &HTMLElementTable, this, propertyName, slot);
 }
 
 bool KJS::HTMLElement::implementsCall() const
@@ -2254,49 +2306,6 @@ Value HTMLElement::getValueProperty(ExecState *exec, int token) const
     return Undefined();
 }
 
-bool KJS::HTMLElement::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
-{
-#ifdef KJS_VERBOSE
-    //kdDebug(6070) << "HTMLElement::hasProperty " << propertyName.qstring() << endl;
-#endif
-    HTMLElementImpl &element = *static_cast<HTMLElementImpl *>(impl());
-    // First look at dynamic properties - keep this in sync with tryGet
-    if (element.hasLocalName(formTag)) {
-        HTMLFormElementImpl &form = static_cast<HTMLFormElementImpl &>(element);
-        // Check if we're retrieving an element (by index or by name)
-        bool ok;
-        uint u = propertyName.toULong(&ok);
-        if (ok && form.elements()->item(u))
-            return true;
-        if (form.elements()->namedItem(propertyName.string()))
-            return true;
-    }
-    else if (element.hasLocalName(selectTag)) {
-        HTMLSelectElementImpl &select = static_cast<HTMLSelectElementImpl &>(element);
-        bool ok;
-        uint u = propertyName.toULong(&ok);
-        if (ok && select.optionsHTMLCollection()->item(u))
-            return true;
-    }
-    else if (element.hasLocalName(inputTag)) {
-        HTMLInputElementImpl &input = static_cast<HTMLInputElementImpl &>(element);
-        const HashTable* table = classInfo()->propHashTable;
-        const HashEntry* entry = Lookup::findEntry(table, propertyName);
-        if (entry) {
-            switch(entry->value) {
-            case InputSelectionStart:
-            case InputSelectionEnd:
-            case InputSetSelectionRange:
-                return input.canHaveSelection();
-            default:
-                break;
-            }
-        }
-    }
-
-    return DOMElement::hasOwnProperty(exec, propertyName);
-}
-
 UString KJS::HTMLElement::toString(ExecState *exec) const
 {
     if (impl()->hasTagName(aTag))
@@ -3351,56 +3360,50 @@ HTMLCollection::~HTMLCollection()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-// We have to implement hasOwnProperty since we don't use a hashtable for 'selectedIndex' and 'length'
-// ## this breaks "for (..in..)" though.
-bool KJS::HTMLCollection::hasOwnProperty(ExecState *exec, const Identifier &p) const
+Value HTMLCollection::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
 {
-  if (p == "selectedIndex" || p == lengthPropertyName)
-    return true;
-  return DOMObject::hasOwnProperty(exec, p);
+    HTMLCollection *thisObj = static_cast<HTMLCollection *>(slot.slotBase());
+    return Number(thisObj->m_impl->length());
 }
 
-bool KJS::HTMLCollection::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value HTMLCollection::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLCollection *thisObj = static_cast<HTMLCollection *>(slot.slotBase());
+    return getDOMNode(exec, thisObj->m_impl->item(slot.index()));
+}
+
+Value HTMLCollection::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLCollection *thisObj = static_cast<HTMLCollection *>(slot.slotBase());
+    return thisObj->getNamedItems(exec, propertyName);
+}
+
+bool HTMLCollection::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  HTMLCollectionImpl &collection = *m_impl;
   if (propertyName == lengthPropertyName) {
-    result = Number(collection.length());
-    return true;
-  } else if (propertyName == "selectedIndex") {
-    // FIXME: should we really handle selectedIndex here, as well as in HTMLSelectCollection?
-
-    // NON-STANDARD options.selectedIndex
-    NodeImpl *option = collection.item(0);
-    if (option->hasTagName(optionTag)) {
-      NodeImpl *select = option;
-      while ((select = select->parentNode()))
-        if (select->hasTagName(selectTag)) {
-         result =  Number(static_cast<HTMLSelectElementImpl *>(select)->selectedIndex());
-          return true;
-        }
-    }
+      slot.setCustom(this, lengthGetter);
+      return true;
   } else {
     // Look in the prototype (for functions) before assuming it's an item's name
     Object proto = Object::dynamicCast(prototype());
-    if (!proto.isNull() && proto.hasProperty(exec,propertyName))
+    if (!proto.isNull() && proto.hasProperty(exec, propertyName))
       return false;
 
     // name or index ?
     bool ok;
     unsigned int u = propertyName.toULong(&ok);
     if (ok) {
-      result = getDOMNode(exec, collection.item(u));
+      slot.setCustomIndex(this, u, indexGetter);
       return true;
     }
 
-    Value items = getNamedItems(exec, propertyName);
-    if (!items.imp()->isUndefined()) {
-      result = items;
+    if (!getNamedItems(exec, propertyName).imp()->isUndefined()) {
+      slot.setCustom(this, nameGetter);
       return true;
     }
   }
 
-  return DOMObject::getOwnProperty(exec, propertyName, result);
+  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 // HTMLCollections are strange objects, they support both get and call,
@@ -3498,14 +3501,21 @@ HTMLSelectCollection::HTMLSelectCollection(ExecState *exec, HTMLCollectionImpl *
 {
 }
 
-bool KJS::HTMLSelectCollection::getOwnProperty(ExecState *exec, const Identifier &p, Value& result) const
+Value HTMLSelectCollection::selectedIndexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    HTMLSelectCollection *thisObj = static_cast<HTMLSelectCollection *>(slot.slotBase());
+    return Number(thisObj->m_element->selectedIndex());
+}
+
+bool HTMLSelectCollection::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  if (p == "selectedIndex") {
-    result = Number(m_element->selectedIndex());
+  if (propertyName == "selectedIndex") {
+    slot.setCustom(this, selectedIndexGetter);
+    //result = Number(m_element->selectedIndex());
     return true;
   }
 
-  return HTMLCollection::getOwnProperty(exec, p, result);
+  return HTMLCollection::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 void KJS::HTMLSelectCollection::put(ExecState *exec, const Identifier &propertyName, const Value& value, int)
@@ -3674,9 +3684,9 @@ const ClassInfo KJS::Image::info = { "Image", 0, &ImageTable, 0 };
 @end
 */
 
-bool Image::getOwnProperty(ExecState *exec, const Identifier &propertyName, Value &result) const
+bool Image::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<Image,DOMObject>(exec, propertyName, &ImageTable, this, result);
+  return getStaticValueSlot<Image,DOMObject>(exec, &ImageTable, this, propertyName, slot);
 }
 
 Value Image::getValueProperty(ExecState *, int token) const
@@ -4696,10 +4706,10 @@ const ClassInfo Context2D::info = { "Context2D", 0, &Context2DTable, 0 };
 @end
 */
 
-bool Context2D::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool Context2D::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
     // FIXME: functions should be on the prototype, not in the object itself
-    return lookupGetOwnProperty<Context2DFunction, Context2D, DOMObject>(exec, propertyName, &Context2DTable, this, result);
+    return getStaticPropertySlot<Context2DFunction, Context2D, DOMObject>(exec, &Context2DTable, this, propertyName, slot);
 }
 
 Value Context2D::getValueProperty(ExecState *, int token) const
@@ -5258,9 +5268,9 @@ Gradient::Gradient(float x0, float y0, float r0, float x1, float y1, float r1)
     commonInit();
 }
 
-bool Gradient::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool Gradient::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    return lookupGetOwnProperty<GradientFunction, Gradient, DOMObject>(exec, propertyName, &GradientTable, this, result);
+    return getStaticPropertySlot<GradientFunction, Gradient, DOMObject>(exec, &GradientTable, this, propertyName, slot);
 }
 
 Value Gradient::getValueProperty(ExecState *, int token) const
@@ -5454,9 +5464,9 @@ CGPatternRef ImagePattern::createPattern(CGAffineTransform transform)
     return CGPatternCreate(this, _bounds, patternTransform, _rw, _rh, kCGPatternTilingConstantSpacing, true, &patternCallbacks);
 }
 
-bool ImagePattern::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool ImagePattern::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    return lookupGetOwnValue<ImagePattern, DOMObject>(exec, propertyName, &ImagePatternTable, this, result);
+    return getStaticValueSlot<ImagePattern, DOMObject>(exec, &ImagePatternTable, this, propertyName, slot);
 }
 
 Value ImagePattern::getValueProperty(ExecState *, int token) const
index 956390e..413ffe9 100644 (file)
@@ -47,26 +47,27 @@ namespace KJS {
   class HTMLDocument : public DOMDocument {
   public:
     HTMLDocument(ExecState *exec, DOM::HTMLDocumentImpl *d);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
     enum { Title, Referrer, Domain, URL, Body, Location, Cookie,
            Images, Applets, Embeds, Links, Forms, Anchors, Scripts, All, Clear, Open, Close,
            Write, WriteLn, GetElementsByName, CaptureEvents, ReleaseEvents,
            BgColor, FgColor, AlinkColor, LinkColor, VlinkColor, LastModified, Height, Width, Dir, DesignMode };
+  private:
+    static Value namedItemGetter(ExecState *, const Identifier&, const PropertySlot&);
   };
 
   class HTMLElement : public DOMElement {
   public:
     HTMLElement(ExecState *exec, DOM::HTMLElementImpl *e);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int);
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &propertyName) const;
     virtual UString toString(ExecState *exec) const;
     virtual void pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const;
     virtual Value call(ExecState *exec, Object &thisObj, const List&args);
@@ -285,6 +286,14 @@ namespace KJS {
            ElementInnerHTML, ElementTitle, ElementId, ElementDir, ElementLang,
            ElementClassName, ElementInnerText, ElementDocument, ElementChildren, ElementContentEditable,
            ElementIsContentEditable, ElementOuterHTML, ElementOuterText};
+  private:
+    static Value formIndexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value formNameGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value selectIndexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value framesetNameGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value frameWindowPropertyGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value runtimeObjectGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value runtimeObjectPropertyGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
   };
 
   DOM::HTMLElementImpl *toHTMLElement(ValueImp *); // returns 0 if passed-in value is not a HTMLElement object
@@ -295,11 +304,10 @@ namespace KJS {
   public:
     HTMLCollection(ExecState *exec, DOM::HTMLCollectionImpl *c);
     ~HTMLCollection();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     virtual Value call(ExecState *exec, Object &thisObj, const List&args);
     virtual bool implementsCall() const { return true; }
     virtual bool toBoolean(ExecState *) const { return true; }
-    virtual bool hasOwnProperty(ExecState *exec, const Identifier &p) const;
     enum { Item, NamedItem, Tags };
     Value getNamedItems(ExecState *exec, const Identifier &propertyName) const;
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -307,14 +315,20 @@ namespace KJS {
     DOM::HTMLCollectionImpl *impl() const { return m_impl.get(); }
   protected:
     khtml::SharedPtr<DOM::HTMLCollectionImpl> m_impl;
+  private:
+    static Value lengthGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value indexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+    static Value nameGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
   };
 
   class HTMLSelectCollection : public HTMLCollection {
   public:
     HTMLSelectCollection(ExecState *exec, DOM::HTMLCollectionImpl *c, DOM::HTMLSelectElementImpl *e);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
   private:
+    static Value selectedIndexGetter(ExecState *exec, const Identifier&, const PropertySlot& slot);
+
     khtml::SharedPtr<DOM::HTMLSelectElementImpl> m_element;
   };
 
@@ -344,7 +358,7 @@ namespace KJS {
   public:
     Image(DOM::DocumentImpl *d, bool ws, int w, bool hs, int h);
     ~Image();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
@@ -374,7 +388,7 @@ namespace KJS {
   public:
     Context2D(DOM::HTMLElementImpl *e);
     ~Context2D();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
@@ -466,7 +480,7 @@ private:
     Gradient(float x0, float y0, float x1, float y1);
     Gradient(float x0, float y0, float r0, float x1, float y1, float r1);
     ~Gradient();
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
@@ -512,7 +526,7 @@ private:
   class ImagePattern : public DOMObject {
   public:
     ImagePattern(Image *i, int type);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
     void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
index 8515625..34c8f37 100644 (file)
@@ -30,7 +30,6 @@
 #include <kio/kprotocolmanager.h>
 #include "kjs_navigator.h"
 #include "kjs/lookup.h"
-#include "kjs_navigator.lut.h"
 #include "kjs_binding.h"
 #include "khtml_part.h"
 
@@ -75,47 +74,66 @@ namespace KJS {
     class Plugins : public PluginBase {
     public:
         Plugins(ExecState *exec) : PluginBase(exec) {};
-        virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+        virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+        Value getValueProperty(ExecState *, int token) const;
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
+        enum { Length, Refresh };
     private:
+        static Value indexGetter(ExecState *, const Identifier&, const PropertySlot&);
+        static Value nameGetter(ExecState *, const Identifier&, const PropertySlot&);
     };
-    const ClassInfo Plugins::info = { "PluginArray", 0, 0, 0 };
-
 
     class MimeTypes : public PluginBase {
     public:
         MimeTypes(ExecState *exec) : PluginBase(exec) { };
-        virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+        virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+        Value getValueProperty(ExecState *, int token) const;
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
+        enum { Length };
     private:
+        static Value indexGetter(ExecState *, const Identifier&, const PropertySlot&);
+        static Value nameGetter(ExecState *, const Identifier&, const PropertySlot&);
     };
-    const ClassInfo MimeTypes::info = { "MimeTypeArray", 0, 0, 0 };
-
 
     class Plugin : public PluginBase {
     public:
         Plugin(ExecState *exec, PluginInfo *info) : PluginBase(exec), m_info(info) { }
-        virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+        virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+        Value getValueProperty(ExecState *, int token) const;
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
+        enum { Name, Filename, Description, Length };
     private:
+        static Value indexGetter(ExecState *, const Identifier&, const PropertySlot&);
+        static Value nameGetter(ExecState *, const Identifier&, const PropertySlot&);
+
         PluginInfo *m_info;
     };
-    const ClassInfo Plugin::info = { "Plugin", 0, 0, 0 };
-
 
     class MimeType : public PluginBase {
     public:
         MimeType( ExecState *exec, MimeClassInfo *info ) : PluginBase(exec), m_info(info) { }
-        virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+        virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+        Value getValueProperty(ExecState *, int token) const;
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
+        enum { Type, Suffixes, Description, EnabledPlugin };
     private:
         MimeClassInfo *m_info;
     };
-    const ClassInfo MimeType::info = { "MimeType", 0, 0, 0 };
+
+} // namespace
+
+#include "kjs_navigator.lut.h"
+
+namespace KJS {
+
+const ClassInfo Plugins::info = { "PluginArray", 0, &PluginsTable, 0 };
+const ClassInfo MimeTypes::info = { "MimeTypeArray", 0, &MimeTypesTable, 0 };
+const ClassInfo Plugin::info = { "Plugin", 0, &PluginTable, 0 };
+const ClassInfo MimeType::info = { "MimeType", 0, &MimeTypeTable, 0 };
 
 QPtrList<PluginBase::PluginInfo> *KJS::PluginBase::plugins = 0;
 QPtrList<PluginBase::MimeClassInfo> *KJS::PluginBase::mimes = 0;
@@ -144,9 +162,9 @@ IMPLEMENT_PROTOFUNC(NavigatorFunc)
 Navigator::Navigator(ExecState *exec, KHTMLPart *p)
   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), m_part(p) { }
 
-bool Navigator::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+bool Navigator::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnProperty<NavigatorFunc, Navigator, ObjectImp>(exec, propertyName, &NavigatorTable, this, result);
+  return getStaticPropertySlot<NavigatorFunc, Navigator, ObjectImp>(exec, &NavigatorTable, this, propertyName, slot);
 }
 
 Value Navigator::getValueProperty(ExecState *exec, int token) const
@@ -334,130 +352,227 @@ void PluginBase::refresh(bool reload)
 
 
 /*******************************************************************/
+
+/*
+@begin PluginsTable 2
+  length       Plugins::Length         DontDelete|ReadOnly
+  refresh      Plugins::Refresh        DontDelete|Function 0
+@end
+*/
 IMPLEMENT_PROTOFUNC(PluginsFunc)
 
-bool Plugins::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+Value Plugins::getValueProperty(ExecState *exec, int token) const
 {
-    if (propertyName == "refresh") {
-        result = lookupOrCreateFunction<PluginsFunc>(exec, propertyName, this, 0, 0, DontDelete|Function);
-        return true;
-    } else if (propertyName == lengthPropertyName) {
-        result = Number(plugins->count());
-        return true;
+  assert(token == length);
+  return Number(plugins->count());
+}
+
+Value Plugins::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    return Value(new Plugin(exec, plugins->at(slot.index())));
+}
+
+Value Plugins::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  for (PluginInfo *pl = plugins->first(); pl; pl = plugins->next()) {
+    if (pl->name == propertyName.qstring()) {
+      return Value(new Plugin(exec, pl));
+    }
+  }
+  return Undefined();
+}
+
+bool Plugins::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    const HashEntry* entry = Lookup::findEntry(&PluginsTable, propertyName);
+    if (entry) {
+      if (entry->attr & Function)
+        slot.setStaticEntry(this, entry, staticFunctionGetter<PluginsFunc>);
+      else
+        slot.setStaticEntry(this, entry, staticValueGetter<Plugins>);
+      return true;
     } else {
         // plugins[#]
         bool ok;
         unsigned int i = propertyName.toULong(&ok);
         if (ok && i < plugins->count()) {
-            result = Value(new Plugin(exec, plugins->at(i)));
+            slot.setCustomIndex(this, i, indexGetter);
             return true;
         }
 
         // plugin[name]
         for (PluginInfo *pl = plugins->first(); pl; pl = plugins->next()) {
-            if (pl->name==propertyName.qstring()) {
-                result = Value(new Plugin(exec, pl));
+            if (pl->name == propertyName.qstring()) {
+                slot.setCustom(this, nameGetter);
                 return true;
             }
         }
     }
 
-    return PluginBase::getOwnProperty(exec, propertyName, result);
+    return PluginBase::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 /*******************************************************************/
 
-bool MimeTypes::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+/*
+@begin MimeTypesTable 1
+  length       MimeTypes::Length       DontDelete|ReadOnly
+@end
+*/
+
+Value MimeTypes::getValueProperty(ExecState *exec, int token) const
 {
-    if (propertyName == lengthPropertyName) {
-        result = Number(mimes->count());
-        return true;
+  assert(token == length);
+  return Number(plugins->count());
+}
+
+Value MimeTypes::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    return Value(new MimeType(exec, mimes->at(slot.index())));
+}
+
+Value MimeTypes::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+  for (MimeClassInfo *m = mimes->first(); m; m = mimes->next()) {
+      if (m->type == propertyName.qstring()) {
+          return Value(new MimeType(exec, m));
+      }
+  }
+  return Undefined();
+}
+
+bool MimeTypes::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    const HashEntry* entry = Lookup::findEntry(&MimeTypesTable, propertyName);
+    if (entry) {
+      slot.setStaticEntry(this, entry, staticValueGetter<Plugins>);
+      return true;
     } else {
         // mimeTypes[#]
         bool ok;
         unsigned int i = propertyName.toULong(&ok);
         if (ok && i < mimes->count()) {
-            result = Value(new MimeType(exec, mimes->at(i)));
+            slot.setCustomIndex(this, i, indexGetter);
             return true;
         }
 
         // mimeTypes[name]
         for (MimeClassInfo *m = mimes->first(); m; m = mimes->next()) {
             if (m->type == propertyName.qstring()) {
-                result = Value(new MimeType(exec, m));
+                slot.setCustom(this, nameGetter);
                 return true;
             }
         }
     }
 
-    return PluginBase::getOwnProperty(exec, propertyName, result);
+    return PluginBase::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 
 /************************************************************************/
 
-bool Plugin::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
+/*
+@begin PluginTable 4
+  name         Plugin::Name            DontDelete|ReadOnly
+  filename     Plugin::Filename        DontDelete|ReadOnly
+  description  Plugin::Description     DontDelete|ReadOnly
+  length       Plugin::Length          DontDelete|ReadOnly
+@end
+*/
+
+Value Plugin::getValueProperty(ExecState *exec, int token) const
 {
-    // FIXME: should use the hashtable mechanism for properties
+    switch (token) {
+    case Name:
+        return String(m_info->name);
+    case Filename:
+        return String(m_info->file);
+    case Description:
+        return String(m_info->desc);
+    case Length: 
+        return Number(m_info->mimes.count());
+    default:
+        assert(0);
+        return Undefined();
+    }
+}
 
-    if (propertyName == "name") {
-        result = String(m_info->name);
-        return true;
-    } else if (propertyName == "filename") {
-        result = String(m_info->file);
-        return true;
-    } else if (propertyName == "description") {
-        result = String(m_info->desc);
-        return true;
-    } else if (propertyName == lengthPropertyName) {
-        result = Number(m_info->mimes.count());
+Value Plugin::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    Plugin *thisObj = static_cast<Plugin *>(slot.slotBase());
+    return Value(new MimeType(exec, thisObj->m_info->mimes.at(slot.index())));
+}
+
+Value Plugin::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
+{
+    Plugin *thisObj = static_cast<Plugin *>(slot.slotBase());
+    for (MimeClassInfo *m = thisObj->m_info->mimes.first(); m; m = thisObj->m_info->mimes.next()) {
+        if (m->type == propertyName.qstring()) {
+            return Value(new MimeType(exec, m));
+        }
+    }
+    return Undefined();
+}
+
+
+bool Plugin::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    const HashEntry* entry = Lookup::findEntry(&PluginTable, propertyName);
+    if (entry) {
+        slot.setStaticEntry(this, entry, staticValueGetter<Plugin>);
         return true;
     } else {
         // plugin[#]
         bool ok;
         unsigned int i = propertyName.toULong(&ok);
         if (ok && i < m_info->mimes.count()) {
-            result = Value(new MimeType(exec, m_info->mimes.at(i)));
-            return result;
+            slot.setCustomIndex(this, i, indexGetter);
+            return true;
         }
 
         // plugin["name"]
         for (MimeClassInfo *m=m_info->mimes.first(); m; m = m_info->mimes.next()) {
-            if (m->type==propertyName.qstring()) {
-                result = Value(new MimeType(exec, m));
-                return result;
+            if (m->type == propertyName.qstring()) {
+                slot.setCustom(this, nameGetter);
+                return true;
             }
         }
-
     }
 
-    return ObjectImp::getOwnProperty(exec, propertyName, result);
+    return PluginBase::getOwnPropertySlot(exec, propertyName, slot);
 }
 
-
 /*****************************************************************************/
 
-bool MimeType::getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const
-{
-    // FIXME: should use hashtable mechanism
+/*
+@begin MimeTypeTable 4
+  type         MimeType::Type          DontDelete|ReadOnly
+  suffixes     MimeType::Suffixes      DontDelete|ReadOnly
+  description  MimeType::Description   DontDelete|ReadOnly
+  enabledPlugin        MimeType::EnabledPlugin DontDelete|ReadOnly
+@end
+*/
 
-    if (propertyName == "type") {
-        result = String(m_info->type);
-        return true;
-    } else if (propertyName == "suffixes") {
-        result = String(m_info->suffixes);
-        return true;
-    } else if (propertyName == "description") {
-        result = String(m_info->desc);
-        return true;
-    } else if (propertyName == "enabledPlugin") {
-        result = Value(new Plugin(exec, m_info->plugin));
-        return true;
+Value MimeType::getValueProperty(ExecState *exec, int token) const
+{
+    switch (token) {
+    case Type:
+        return String(m_info->type);
+    case Suffixes:
+        return String(m_info->suffixes);
+    case Description:
+        return String(m_info->desc);
+    case EnabledPlugin:
+        return Value(new Plugin(exec, m_info->plugin));
+    default:
+        return Undefined();
     }
-
-    return ObjectImp::getOwnProperty(exec, propertyName, result);
 }
 
+bool MimeType::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    return getStaticValueSlot<MimeType, PluginBase>(exec, &MimeTypeTable, this, propertyName, slot);
+}
 
 Value PluginsFunc::call(ExecState *exec, Object &, const List &args)
 {
@@ -465,7 +580,6 @@ Value PluginsFunc::call(ExecState *exec, Object &, const List &args)
     return Undefined();
 }
 
-
 Value NavigatorFunc::call(ExecState *exec, Object &thisObj, const List &)
 {
   if (!thisObj.inherits(&KJS::Navigator::info)) {
index f55e86a..46a7268 100644 (file)
@@ -30,7 +30,7 @@ namespace KJS {
   class Navigator : public ObjectImp {
   public:
     Navigator(ExecState *exec, KHTMLPart *p);
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
index dd4a457..a6b96a3 100644 (file)
@@ -83,9 +83,9 @@ DOMRange::~DOMRange()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMRange::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMRange::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMRange, DOMObject>(exec, p, &DOMRangeTable, this, result);
+  return getStaticValueSlot<DOMRange, DOMObject>(exec, &DOMRangeTable, this, propertyName, slot);
 }
 
 Value DOMRange::getValueProperty(ExecState *exec, int token) const
@@ -204,9 +204,9 @@ const ClassInfo RangeConstructor::info = { "RangeConstructor", 0, &RangeConstruc
   END_TO_START         DOM::Range::END_TO_START        DontDelete|ReadOnly
 @end
 */
-bool RangeConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool RangeConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<RangeConstructor,DOMObject>(exec, p, &RangeConstructorTable, this, result);
+  return getStaticValueSlot<RangeConstructor,DOMObject>(exec, &RangeConstructorTable, this, propertyName, slot);
 }
 
 Value RangeConstructor::getValueProperty(ExecState *, int token) const
index 103d88f..e6fd4c6 100644 (file)
@@ -33,7 +33,7 @@ namespace KJS {
   public:
     DOMRange(ExecState *exec, DOM::RangeImpl *r);
     ~DOMRange();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -54,7 +54,7 @@ namespace KJS {
   class RangeConstructor : public DOMObject {
   public:
     RangeConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
index 8a57ffb..e524c27 100644 (file)
@@ -68,9 +68,9 @@ DOMNodeIterator::~DOMNodeIterator()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMNodeIterator::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMNodeIterator::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMNodeIterator, DOMObject>(exec, p, &DOMNodeIteratorTable, this, result);
+  return getStaticValueSlot<DOMNodeIterator, DOMObject>(exec, &DOMNodeIteratorTable, this, propertyName, slot);
 }
 
 Value DOMNodeIterator::getValueProperty(ExecState *exec, int token) const
@@ -145,9 +145,9 @@ const ClassInfo NodeFilterConstructor::info = { "NodeFilterConstructor", 0, &Nod
   SHOW_NOTATION                DOM::NodeFilter::SHOW_NOTATION  DontDelete|ReadOnly
 @end
 */
-bool NodeFilterConstructor::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool NodeFilterConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<NodeFilterConstructor, DOMObject>(exec, p, &NodeFilterConstructorTable, this, result);
+  return getStaticValueSlot<NodeFilterConstructor, DOMObject>(exec, &NodeFilterConstructorTable, this, propertyName, slot);
 }
 
 Value NodeFilterConstructor::getValueProperty(ExecState *, int token) const
@@ -247,9 +247,9 @@ DOMTreeWalker::~DOMTreeWalker()
   ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMTreeWalker::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool DOMTreeWalker::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<DOMTreeWalker, DOMObject>(exec, p, &DOMTreeWalkerTable, this, result);
+  return getStaticValueSlot<DOMTreeWalker, DOMObject>(exec, &DOMTreeWalkerTable, this, propertyName, slot);
 }
 
 Value DOMTreeWalker::getValueProperty(ExecState *exec, int token) const
index 6d37d42..ee4c221 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "kjs_dom.h"
 #include "dom/dom2_traversal.h"
+#include <kjs/protected_object.h>
 
 namespace DOM {
     class NodeFilterImpl;
@@ -36,7 +37,7 @@ namespace KJS {
   public:
     DOMNodeIterator(ExecState *exec, DOM::NodeIteratorImpl *ni);
     ~DOMNodeIterator();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -52,7 +53,7 @@ namespace KJS {
   class NodeFilterConstructor : public DOMObject {
   public:
     NodeFilterConstructor(ExecState *) { }
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot& slot);
     Value getValueProperty(ExecState *exec, int token) const;
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
@@ -76,7 +77,7 @@ namespace KJS {
   public:
     DOMTreeWalker(ExecState *exec, DOM::TreeWalkerImpl *tw);
     ~DOMTreeWalker();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot& slot);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName,
                         const Value& value, int attr = None);
index 169da00..c75b62c 100644 (file)
@@ -51,20 +51,18 @@ IMPLEMENT_PROTOFUNC(DOMAbstractViewFunc)
 
 DOMAbstractView::~DOMAbstractView()
 {
-  ScriptInterpreter::forgetDOMObject(m_impl.get());
+    ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-bool DOMAbstractView::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value DOMAbstractView::getValueProperty(ExecState *exec, int token)
 {
-    if (p == "document") {
-        result = getDOMNode(exec, m_impl->document());
-        return true;
-    } else if (p == "getComputedStyle") {
-        result = lookupOrCreateFunction<DOMAbstractViewFunc>(exec, p, this, DOMAbstractView::GetComputedStyle, 2, DontDelete|Function);
-        return true;
-    }
-
-    return DOMObject::getOwnProperty(exec, p, result);
+    assert(token == Document);
+    return getDOMNode(exec, impl()->document());
+}
+
+bool DOMAbstractView::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    return getStaticPropertySlot<DOMAbstractViewFunc, DOMAbstractView, DOMObject>(exec, &DOMAbstractViewTable, this, propertyName, slot);
 }
 
 Value DOMAbstractViewFunc::call(ExecState *exec, Object &thisObj, const List &args)
index 0f10f21..2d248d2 100644 (file)
@@ -33,7 +33,8 @@ namespace KJS {
   public:
     DOMAbstractView(ExecState *, DOM::AbstractViewImpl *av) : m_impl(av) { }
     ~DOMAbstractView();
-    virtual bool getOwnProperty(ExecState *exec,const Identifier& p, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token);
     // no put - all read-only
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
index b19bd1f..f7863b3 100644 (file)
@@ -104,7 +104,7 @@ namespace KJS {
   public:
     History(ExecState *exec, KHTMLPart *p)
       : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
     Value getValueProperty(ExecState *exec, int token) const;
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
@@ -118,9 +118,17 @@ namespace KJS {
   public:
     FrameArray(ExecState *exec, KHTMLPart *p)
       : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
-    virtual bool getOwnProperty(ExecState *exec, const Identifier& propertyName, Value& result) const;
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    Value getValueProperty(ExecState *exec, int token);
     virtual UString toString(ExecState *exec) const;
+    enum { Length, Location };
   private:
+    static Value indexGetter(ExecState *, const Identifier&, const PropertySlot&);
+    static Value nameGetter(ExecState *, const Identifier&, const PropertySlot&);
+
+    virtual const ClassInfo* classInfo() const { return &info; }
+    static const ClassInfo info;
+
     QGuardedPtr<KHTMLPart> part;
   };
 
@@ -165,9 +173,9 @@ const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
 Screen::Screen(ExecState *exec)
   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()) {}
 
-bool Screen::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+bool Screen::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return lookupGetOwnValue<Screen, ObjectImp>(exec, p, &ScreenTable, this, result);
+  return getStaticValueSlot<Screen, ObjectImp>(exec, &ScreenTable, this, propertyName, slot);
 }
 
 Value Screen::getValueProperty(ExecState *exec, int token) const
@@ -688,179 +696,106 @@ static ValueImp *showModalDialog(ExecState *exec, Window *openerWindow, const Li
     return returnValue;
 }
 
-bool Window::getOwnProperty(ExecState *exec, const Identifier& p, Value& result) const
+Value Window::getValueProperty(ExecState *exec, int token) const
 {
-  if (p == "closed") {
-      result = Boolean(m_part.isNull());
-      return false;
-  }
-
-  // we don't want any properties other than "closed" on a closed window
-  if (m_part.isNull()) {
-      result = Undefined();
-      return true;
-  }
-
-  // Look for overrides first
-  ValueImp * val = ObjectImp::getDirect(p);
-  if (val) {
-    if (isSafeScript(exec))
-      result = Value(val);
-    else
-      result = Undefined();
-    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.
-  KHTMLPart *childFrame = m_part->childFrameNamed(p.ustring().qstring());
-  if (childFrame) {
-    result = retrieve(childFrame);
-    return true;
-  }
+   assert(token == Closed || m_part);
 
-  const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
-  if (entry) {
-    switch(entry->value) {
-    case Crypto:
-      result = Undefined(); // ###
-      return true;
-    case DefaultStatus:
-      result = String(UString(m_part->jsDefaultStatusBarText()));
-      return true;
-    case Status:
-      result = String(UString(m_part->jsStatusBarText()));
-      return true;
-    case Document:
-      if (isSafeScript(exec)) {
-        if (!m_part->xmlDocImpl()) {
-#if APPLE_CHANGES
-          KWQ(m_part)->createEmptyDocument();
-#endif
-          m_part->begin();
-          m_part->write("<HTML><BODY>");
-          m_part->end();
-        }
-        result = getDOMNode(exec, m_part->xmlDocImpl());
-      } else
-        result = Undefined();
-      return true;
+   switch (token) {
+   case Closed:
+      return Boolean(m_part.isNull());
+   case Crypto:
+      return Undefined(); // ###
+   case DefaultStatus:
+      return String(UString(m_part->jsDefaultStatusBarText()));
+   case Status:
+      return String(UString(m_part->jsStatusBarText()));
     case Node:
-      result = getNodeConstructor(exec);
-      return true;
+      return getNodeConstructor(exec);
     case Range:
-      result = getRangeConstructor(exec);
-      return true;
+      return getRangeConstructor(exec);
     case NodeFilter:
-      result = getNodeFilterConstructor(exec);
-      return true;
+      return getNodeFilterConstructor(exec);
     case DOMException:
-      result = getDOMExceptionConstructor(exec);
-      return true;
+      return getDOMExceptionConstructor(exec);
     case CSSRule:
-      result = getCSSRuleConstructor(exec);
-      return true;
+      return getCSSRuleConstructor(exec);
     case EventCtor:
-      result = getEventConstructor(exec);
-      return true;
+      return getEventConstructor(exec);
     case Frames:
-      result = Value(frames ? frames :
-                     (const_cast<Window*>(this)->frames = new FrameArray(exec,m_part)));
-      return true;
+      if (!frames)
+        frames = new FrameArray(exec, m_part);
+      return frames;
     case _History:
-      result = Value(history ? history :
-                     (const_cast<Window*>(this)->history = new History(exec,m_part)));
-      return true;
+      if (!history)
+        history = new History(exec, m_part);
+      return history;
     case Event:
-      if (m_evt)
-        result = getDOMEvent(exec, m_evt);
-      else
-        result = Undefined();
-      return true;
+      if (!m_evt)
+        return Undefined();
+      return getDOMEvent(exec, m_evt);
     case InnerHeight:
-      if (m_part->view())
-        result = Number(m_part->view()->visibleHeight());
-      else
-        result = Undefined();
-      return true;
+      if (!m_part->view())
+        return Undefined();
+      return Number(m_part->view()->visibleHeight());
     case InnerWidth:
-      if (m_part->view())
-        result = Number(m_part->view()->visibleWidth());
-      else
-        result = Undefined();
-      return true;
+      if (!m_part->view())
+        return Undefined();
+      return Number(m_part->view()->visibleWidth());
     case Length:
-      result = Number(m_part->frames().count());
-      return true;
+      return Number(m_part->frames().count());
     case _Location:
-      result = Value(location());
-      return true;
+      return location();
     case Name:
-      result = String(m_part->name());
-      return true;
+      return String(m_part->name());
     case _Navigator:
     case ClientInformation: {
       // Store the navigator in the object so we get the same one each time.
       Navigator *n = new Navigator(exec, m_part);
+      // FIXME: this will make the "navigator" object accessible from windows that fail
+      // the security check the first time, but not subsequent times, seems weird.
       const_cast<Window *>(this)->putDirect("navigator", n, DontDelete|ReadOnly);
       const_cast<Window *>(this)->putDirect("clientInformation", n, DontDelete|ReadOnly);
-      result = Value(n);
-      return true;
+      return Value(n);
     }
 #ifdef Q_WS_QWS
     case _Konqueror:
-      result = Value(new Konqueror(m_part));
-      return true;
+      return Value(new Konqueror(m_part));
 #endif
     case Locationbar:
-      result = Value(locationbar(exec));
-      return true;
+      return locationbar(exec);
     case Menubar:
-      result = Value(menubar(exec));
-      return true;
+      return menubar(exec);
     case OffscreenBuffering:
-      result = Boolean(true);
-      return true;
+      return Boolean(true);
     case Opener:
       if (m_part->opener())
-        result = retrieve(m_part->opener());
+        return retrieve(m_part->opener());
       else
-        result = Null();
-      return true;
+        return Null();
     case OuterHeight:
     case OuterWidth:
     {
       if (m_part->view()) {
         KWin::Info inf = KWin::info(m_part->view()->topLevelWidget()->winId());
-        result = Number(entry->value == OuterHeight ?
-                        inf.geometry.height() : inf.geometry.width());
+        return Number(token == OuterHeight ?
+                      inf.geometry.height() : inf.geometry.width());
       } else
-        result = Number(0);
-      return true;
+        return Number(0);
     }
     case PageXOffset:
-      if (m_part->view()) {
-        updateLayout();
-        result = Number(m_part->view()->contentsX());
-      } else
-        result = Undefined();
-      return true;
+      if (!m_part->view())
+        return Undefined();
+      updateLayout();
+      return Number(m_part->view()->contentsX());
     case PageYOffset:
-      if (m_part->view()) {
-        updateLayout();
-        result = Number(m_part->view()->contentsY());
-      } else
-        result = Undefined();
-      return true;
+      if (!m_part->view())
+        return Undefined();
+      updateLayout();
+      return Number(m_part->view()->contentsY());
     case Parent:
-      result = Value(retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part));
-      return true;
+      return Value(retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part));
     case Personalbar:
-      result = Value(personalbar(exec));
-      return true;
+      return Value(personalbar(exec));
     case ScreenLeft:
     case ScreenX: {
       if (m_part->view()) {
@@ -869,308 +804,261 @@ bool Window::getOwnProperty(ExecState *exec, const Identifier& p, Value& result)
         // the windowFrame method of the WebKit's UI delegate. Also we don't want to try
         // to do anything relative to the screen the window is on, so the code below is no
         // good of us anyway.
-        result = Number(m_part->view()->topLevelWidget()->frameGeometry().x());
+        return Number(m_part->view()->topLevelWidget()->frameGeometry().x());
 #else
         QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
-        result = Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
+        return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
 #endif
       } else
-        result = Undefined();
-      return true;
+        return Undefined();
     }
     case ScreenTop:
     case ScreenY: {
       if (m_part->view()) {
 #if APPLE_CHANGES
         // See comment above in ScreenX.
-        result = Number(m_part->view()->topLevelWidget()->frameGeometry().y());
+        return Number(m_part->view()->topLevelWidget()->frameGeometry().y());
 #else
         QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
-        result = Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
+        return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
 #endif
       } else 
-        result = Undefined();
-      return true;
+        return Undefined();
     }
     case ScrollX:
-      if (m_part->view()) {
-        updateLayout();
-        result = Number(m_part->view()->contentsX());
-      } else
-        result = Undefined();
-      return true;
+      if (!m_part->view())
+        return Undefined();
+      updateLayout();
+      return Number(m_part->view()->contentsX());
     case ScrollY:
-      if (m_part->view()) {
-        updateLayout();
-        result = Number(m_part->view()->contentsY());
-      } else
-        result = Undefined();
-      return true;
+      if (!m_part->view())
+        return Undefined();
+      updateLayout();
+      return Number(m_part->view()->contentsY());
     case Scrollbars:
-      result = Value(scrollbars(exec));
-      return true;
+      return Value(scrollbars(exec));
     case Statusbar:
-      result = Value(statusbar(exec));
-      return true;
+      return Value(statusbar(exec));
     case Toolbar:
-      result = Value(toolbar(exec));
-      return true;
+      return Value(toolbar(exec));
     case Self:
     case _Window:
-      result = Value(retrieve(m_part));
-      return true;
+      return Value(retrieve(m_part));
     case Top: {
       KHTMLPart *p = m_part;
       while (p->parentPart())
         p = p->parentPart();
-      result = Value(retrieve(p));
-      return true;
+      return retrieve(p);
     }
     case _Screen:
-      result = Value(screen ? screen :
-                     (const_cast<Window*>(this)->screen = new Screen(exec)));
-      return true;
+      if (!screen)
+        screen = new Screen(exec);
+      return screen;
     case Image:
       // FIXME: this property (and the few below) probably shouldn't create a new object every
       // time
-      result = new ImageConstructorImp(exec, m_part->xmlDocImpl());
-      return true;
+      return new ImageConstructorImp(exec, m_part->xmlDocImpl());
     case Option:
-      result = new OptionConstructorImp(exec, m_part->xmlDocImpl());
-      return true;
+      return new OptionConstructorImp(exec, m_part->xmlDocImpl());
     case XMLHttpRequest:
-      result = new XMLHttpRequestConstructorImp(exec, m_part->xmlDocImpl());
-      return true;
+      return new XMLHttpRequestConstructorImp(exec, m_part->xmlDocImpl());
     case XMLSerializer:
-      result = new XMLSerializerConstructorImp(exec);
-      return true;
+      return new XMLSerializerConstructorImp(exec);
     case DOMParser:
-      result = new DOMParserConstructorImp(exec, m_part->xmlDocImpl());
-      return true;
-    case Focus:
-    case Blur:
-    case Close:
-      result = lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
-      return true;
-    case ShowModalDialog:
-        if (!canShowModalDialog(this))
-          return false;
-        // fall through
-    case Alert:
-    case Confirm:
-    case Prompt:
-    case Open:
-#if APPLE_CHANGES
-    case Print:
-#endif
-    case Scroll: // compatibility
-    case ScrollBy:
-    case ScrollTo:
-    case MoveBy:
-    case MoveTo:
-    case ResizeBy:
-    case ResizeTo:
-    case CaptureEvents:
-    case ReleaseEvents:
-    case AddEventListener:
-    case RemoveEventListener:
-    case SetTimeout:
-    case ClearTimeout:
-    case SetInterval:
-    case ClearInterval:
-    case GetSelection:
-      if (isSafeScript(exec))
-        result = lookupOrCreateFunction<WindowFunc>(exec, p, this, entry->value, entry->params, entry->attr);
-      else
-        result = Undefined();
-      return true;
-    case Onabort:
-      if (isSafeScript(exec))
-        result = getListener(exec,DOM::EventImpl::ABORT_EVENT);
-      else
-        result = Undefined();
-      return true;
-    case Onblur:
-      if (isSafeScript(exec))
-        result = getListener(exec,DOM::EventImpl::BLUR_EVENT);
-      else
-        result = Undefined();
-      return true;
-    case Onchange:
-      if (isSafeScript(exec))
-        result = getListener(exec,DOM::EventImpl::CHANGE_EVENT);
-      else
-        result = Undefined();
-      return true;
-    case Onclick:
-      if (isSafeScript(exec))
-        result = getListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT);
-      else
-        result = Undefined();
-      return true;
-    case Ondblclick:
-      if (isSafeScript(exec))
-        result = getListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT);
-      else
-        result = Undefined();
-      return true;
-    case&n