JavaScriptCore:
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Nov 2007 20:31:26 +0000 (20:31 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Nov 2007 20:31:26 +0000 (20:31 +0000)
        Reviewed by Darin.

        Convert JavaScript internal function objects to use one class per
        function.  This avoids a switch statement inside what used to be
        the shared function classes and will allow Shark to better analyze
        the code.

        To make this switch, the value property of the HashEntry was changed
        to a union of an intptr_t (which is used to continue handle valueGetters)
        and function pointer which points to a static constructor for the
        individual new function objects.

        SunSpider claims this is a 0.5% speedup.

        * kjs/array_object.cpp:
        (KJS::ArrayPrototype::getOwnPropertySlot):
        (KJS::getProperty):
        (KJS::ArrayProtoFuncToString::callAsFunction):
        (KJS::ArrayProtoFuncToLocaleString::callAsFunction):
        (KJS::ArrayProtoFuncJoin::callAsFunction):
        (KJS::ArrayProtoFuncConcat::callAsFunction):
        (KJS::ArrayProtoFuncPop::callAsFunction):
        (KJS::ArrayProtoFuncPush::callAsFunction):
        (KJS::ArrayProtoFuncReverse::callAsFunction):
        (KJS::ArrayProtoFuncShift::callAsFunction):
        (KJS::ArrayProtoFuncSlice::callAsFunction):
        (KJS::ArrayProtoFuncSort::callAsFunction):
        (KJS::ArrayProtoFuncSplice::callAsFunction):
        (KJS::ArrayProtoFuncUnShift::callAsFunction):
        (KJS::ArrayProtoFuncFilter::callAsFunction):
        (KJS::ArrayProtoFuncMap::callAsFunction):
        (KJS::ArrayProtoFuncEvery::callAsFunction):
        (KJS::ArrayProtoFuncForEach::callAsFunction):
        (KJS::ArrayProtoFuncSome::callAsFunction):
        (KJS::ArrayProtoFuncIndexOf::callAsFunction):
        (KJS::ArrayProtoFuncLastIndexOf::callAsFunction):
        * kjs/array_object.h:
        (KJS::ArrayPrototype::classInfo):
        * kjs/create_hash_table:
        * kjs/date_object.cpp:
        (KJS::DatePrototype::getOwnPropertySlot):
        (KJS::DateProtoFuncToString::callAsFunction):
        (KJS::DateProtoFuncToUTCString::callAsFunction):
        (KJS::DateProtoFuncToDateString::callAsFunction):
        (KJS::DateProtoFuncToTimeString::callAsFunction):
        (KJS::DateProtoFuncToLocaleString::callAsFunction):
        (KJS::DateProtoFuncToLocaleDateString::callAsFunction):
        (KJS::DateProtoFuncToLocaleTimeString::callAsFunction):
        (KJS::DateProtoFuncValueOf::callAsFunction):
        (KJS::DateProtoFuncGetTime::callAsFunction):
        (KJS::DateProtoFuncGetFullYear::callAsFunction):
        (KJS::DateProtoFuncGetUTCFullYear::callAsFunction):
        (KJS::DateProtoFuncToGMTString::callAsFunction):
        (KJS::DateProtoFuncGetMonth::callAsFunction):
        (KJS::DateProtoFuncGetUTCMonth::callAsFunction):
        (KJS::DateProtoFuncGetDate::callAsFunction):
        (KJS::DateProtoFuncGetUTCDate::callAsFunction):
        (KJS::DateProtoFuncGetDay::callAsFunction):
        (KJS::DateProtoFuncGetUTCDay::callAsFunction):
        (KJS::DateProtoFuncGetHours::callAsFunction):
        (KJS::DateProtoFuncGetUTCHours::callAsFunction):
        (KJS::DateProtoFuncGetMinutes::callAsFunction):
        (KJS::DateProtoFuncGetUTCMinutes::callAsFunction):
        (KJS::DateProtoFuncGetSeconds::callAsFunction):
        (KJS::DateProtoFuncGetUTCSeconds::callAsFunction):
        (KJS::DateProtoFuncGetMilliSeconds::callAsFunction):
        (KJS::DateProtoFuncGetUTCMilliseconds::callAsFunction):
        (KJS::DateProtoFuncGetTimezoneOffset::callAsFunction):
        (KJS::DateProtoFuncSetTime::callAsFunction):
        (KJS::DateProtoFuncSetMilliSeconds::callAsFunction):
        (KJS::DateProtoFuncSetUTCMilliseconds::callAsFunction):
        (KJS::DateProtoFuncSetSeconds::callAsFunction):
        (KJS::DateProtoFuncSetUTCSeconds::callAsFunction):
        (KJS::DateProtoFuncSetMinutes::callAsFunction):
        (KJS::DateProtoFuncSetUTCMinutes::callAsFunction):
        (KJS::DateProtoFuncSetHours::callAsFunction):
        (KJS::DateProtoFuncSetUTCHours::callAsFunction):
        (KJS::DateProtoFuncSetDate::callAsFunction):
        (KJS::DateProtoFuncSetUTCDate::callAsFunction):
        (KJS::DateProtoFuncSetMonth::callAsFunction):
        (KJS::DateProtoFuncSetUTCMonth::callAsFunction):
        (KJS::DateProtoFuncSetFullYear::callAsFunction):
        (KJS::DateProtoFuncSetUTCFullYear::callAsFunction):
        (KJS::DateProtoFuncSetYear::callAsFunction):
        (KJS::DateProtoFuncGetYear::callAsFunction):
        * kjs/date_object.h:
        * kjs/lookup.cpp:
        (KJS::Lookup::find):
        * kjs/lookup.h:
        (KJS::HashEntry::):
        (KJS::staticFunctionGetter):
        (KJS::staticValueGetter):
        (KJS::getStaticPropertySlot):
        (KJS::getStaticFunctionSlot):
        (KJS::lookupPut):
        * kjs/math_object.cpp:
        (KJS::MathObjectImp::getOwnPropertySlot):
        (KJS::MathProtoFuncAbs::callAsFunction):
        (KJS::MathProtoFuncACos::callAsFunction):
        (KJS::MathProtoFuncASin::callAsFunction):
        (KJS::MathProtoFuncATan::callAsFunction):
        (KJS::MathProtoFuncATan2::callAsFunction):
        (KJS::MathProtoFuncCeil::callAsFunction):
        (KJS::MathProtoFuncCos::callAsFunction):
        (KJS::MathProtoFuncExp::callAsFunction):
        (KJS::MathProtoFuncFloor::callAsFunction):
        (KJS::MathProtoFuncLog::callAsFunction):
        (KJS::MathProtoFuncMax::callAsFunction):
        (KJS::MathProtoFuncMin::callAsFunction):
        (KJS::MathProtoFuncPow::callAsFunction):
        (KJS::MathProtoFuncRandom::callAsFunction):
        (KJS::MathProtoFuncRound::callAsFunction):
        (KJS::MathProtoFuncSin::callAsFunction):
        (KJS::MathProtoFuncSqrt::callAsFunction):
        (KJS::MathProtoFuncTan::callAsFunction):
        * kjs/math_object.h:
        (KJS::MathObjectImp::classInfo):
        (KJS::MathObjectImp::):
        * kjs/string_object.cpp:
        (KJS::StringPrototype::getOwnPropertySlot):
        (KJS::StringProtoFuncToString::callAsFunction):
        (KJS::StringProtoFuncValueOf::callAsFunction):
        (KJS::StringProtoFuncCharAt::callAsFunction):
        (KJS::StringProtoFuncCharCodeAt::callAsFunction):
        (KJS::StringProtoFuncConcat::callAsFunction):
        (KJS::StringProtoFuncIndexOf::callAsFunction):
        (KJS::StringProtoFuncLastIndexOf::callAsFunction):
        (KJS::StringProtoFuncMatch::callAsFunction):
        (KJS::StringProtoFuncSearch::callAsFunction):
        (KJS::StringProtoFuncReplace::callAsFunction):
        (KJS::StringProtoFuncSlice::callAsFunction):
        (KJS::StringProtoFuncSplit::callAsFunction):
        (KJS::StringProtoFuncSubstr::callAsFunction):
        (KJS::StringProtoFuncSubstring::callAsFunction):
        (KJS::StringProtoFuncToLowerCase::callAsFunction):
        (KJS::StringProtoFuncToUpperCase::callAsFunction):
        (KJS::StringProtoFuncToLocaleLowerCase::callAsFunction):
        (KJS::StringProtoFuncToLocaleUpperCase::callAsFunction):
        (KJS::StringProtoFuncLocaleCompare::callAsFunction):
        (KJS::StringProtoFuncBig::callAsFunction):
        (KJS::StringProtoFuncSmall::callAsFunction):
        (KJS::StringProtoFuncBlink::callAsFunction):
        (KJS::StringProtoFuncBold::callAsFunction):
        (KJS::StringProtoFuncFixed::callAsFunction):
        (KJS::StringProtoFuncItalics::callAsFunction):
        (KJS::StringProtoFuncStrike::callAsFunction):
        (KJS::StringProtoFuncSub::callAsFunction):
        (KJS::StringProtoFuncSup::callAsFunction):
        (KJS::StringProtoFuncFontcolor::callAsFunction):
        (KJS::StringProtoFuncFontsize::callAsFunction):
        (KJS::StringProtoFuncAnchor::callAsFunction):
        (KJS::StringProtoFuncLink::callAsFunction):
        * kjs/string_object.h:

WebCore:

        Reviewed by Darin.

        Convert JavaScript internal function objects to use one class per
        function.  This avoids a switch statement inside what used to be
        the shared function classes and will allow Shark to better analyze
        the code.

        To make this switch, the value property of the HashEntry was changed
        to a union of an intptr_t (which is used to continue handle valueGetters)
        and function pointer which points to a static constructor for the
        individual new function objects.

        SunSpider claims this is a 0.5% speedup.

        - On the WebCore side, I updated CodeGeneratorJS.pm to generate the
          new classes and hand updated the remain non-generated (groan) classes.

        * bindings/js/JSDOMWindowCustom.cpp:
        (WebCore::JSDOMWindow::customGetOwnPropertySlot):
        * bindings/js/JSEventTargetNode.cpp:
        (WebCore::JSEventTargetNodePrototypeFunctionAddEventListener::callAsFunction):
        (WebCore::JSEventTargetNodePrototypeFunctionRemoveEventListener::callAsFunction):
        (WebCore::JSEventTargetNodePrototypeFunctionDispatchEvent::callAsFunction):
        * bindings/js/JSEventTargetNode.h:
        * bindings/js/JSHTMLInputElementBase.cpp:
        (WebCore::JSHTMLInputElementBaseFunctionSetSelectionRange::callAsFunction):
        (WebCore::JSHTMLInputElementBase::getOwnPropertySlot):
        * bindings/js/JSHTMLInputElementBase.h:
        (WebCore::JSHTMLInputElementBase::):
        * bindings/js/JSXMLHttpRequest.cpp:
        (KJS::JSXMLHttpRequestPrototypeFunctionAbort::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionGetAllResponseHeaders::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionGetResponseHeader::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionOpen::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionSend::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionSetRequestHeader::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionOverrideMIMEType::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionAddEventListener::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionRemoveEventListener::callAsFunction):
        (KJS::JSXMLHttpRequestPrototypeFunctionDispatchEvent::callAsFunction):
        * bindings/js/JSXMLHttpRequest.h:
        (KJS::JSXMLHttpRequest::impl):
        * bindings/js/JSXSLTProcessor.cpp:
        (KJS::JSXSLTProcessorPrototypeFunctionImportStylesheet::callAsFunction):
        (KJS::JSXSLTProcessorPrototypeFunctionTransformToFragment::callAsFunction):
        (KJS::JSXSLTProcessorPrototypeFunctionTransformToDocument::callAsFunction):
        (KJS::JSXSLTProcessorPrototypeFunctionSetParameter::callAsFunction):
        (KJS::JSXSLTProcessorPrototypeFunctionGetParameter::callAsFunction):
        (KJS::JSXSLTProcessorPrototypeFunctionRemoveParameter::callAsFunction):
        (KJS::JSXSLTProcessorPrototypeFunctionClearParameters::callAsFunction):
        (KJS::JSXSLTProcessorPrototypeFunctionReset::callAsFunction):
        * bindings/js/JSXSLTProcessor.h:
        * bindings/js/kjs_events.cpp:
        (WebCore::JSClipboardPrototypeFunctionClearData::callAsFunction):
        (WebCore::JSClipboardPrototypeFunctionGetData::callAsFunction):
        (WebCore::JSClipboardPrototypeFunctionSetData::callAsFunction):
        (WebCore::JSClipboardPrototypeFunctionSetDragImage::callAsFunction):
        * bindings/js/kjs_events.h:
        * bindings/js/kjs_navigator.cpp:
        (KJS::Plugins::):
        (KJS::Navigator::getOwnPropertySlot):
        (KJS::Plugins::getOwnPropertySlot):
        (KJS::PluginsFunctionRefresh::callAsFunction):
        (KJS::NavigatorProtoFuncJavaEnabled::callAsFunction):
        * bindings/js/kjs_navigator.h:
        (KJS::Navigator::):
        * bindings/js/kjs_window.cpp:
        (KJS::Window::getOwnPropertySlot):
        (KJS::Window::put):
        (KJS::WindowProtoFuncAToB::callAsFunction):
        (KJS::WindowProtoFuncBToA::callAsFunction):
        (KJS::WindowProtoFuncOpen::callAsFunction):
        (KJS::WindowProtoFuncScrollBy::callAsFunction):
        (KJS::WindowProtoFuncScrollTo::callAsFunction):
        (KJS::WindowProtoFuncMoveBy::callAsFunction):
        (KJS::WindowProtoFuncMoveTo::callAsFunction):
        (KJS::WindowProtoFuncResizeBy::callAsFunction):
        (KJS::WindowProtoFuncResizeTo::callAsFunction):
        (KJS::WindowProtoFuncSetTimeout::callAsFunction):
        (KJS::WindowProtoFuncClearTimeout::callAsFunction):
        (KJS::WindowProtoFuncSetInterval::callAsFunction):
        (KJS::WindowProtoFuncAddEventListener::callAsFunction):
        (KJS::WindowProtoFuncRemoveEventListener::callAsFunction):
        (KJS::WindowProtoFuncShowModalDialog::callAsFunction):
        (KJS::WindowProtoFuncNotImplemented::callAsFunction):
        (KJS::Location::getOwnPropertySlot):
        (KJS::Location::put):
        (KJS::LocationProtoFuncReplace::callAsFunction):
        (KJS::LocationProtoFuncReload::callAsFunction):
        (KJS::LocationProtoFuncAssign::callAsFunction):
        (KJS::LocationProtoFuncToString::callAsFunction):
        * bindings/js/kjs_window.h:
        (KJS::Window::):
        * bindings/scripts/CodeGeneratorJS.pm:

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

29 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/kjs/array_object.cpp
JavaScriptCore/kjs/array_object.h
JavaScriptCore/kjs/create_hash_table
JavaScriptCore/kjs/date_object.cpp
JavaScriptCore/kjs/date_object.h
JavaScriptCore/kjs/lookup.cpp
JavaScriptCore/kjs/lookup.h
JavaScriptCore/kjs/math_object.cpp
JavaScriptCore/kjs/math_object.h
JavaScriptCore/kjs/string_object.cpp
JavaScriptCore/kjs/string_object.h
WebCore/ChangeLog
WebCore/bindings/js/JSDOMWindowCustom.cpp
WebCore/bindings/js/JSEventTargetNode.cpp
WebCore/bindings/js/JSEventTargetNode.h
WebCore/bindings/js/JSHTMLInputElementBase.cpp
WebCore/bindings/js/JSHTMLInputElementBase.h
WebCore/bindings/js/JSXMLHttpRequest.cpp
WebCore/bindings/js/JSXMLHttpRequest.h
WebCore/bindings/js/JSXSLTProcessor.cpp
WebCore/bindings/js/JSXSLTProcessor.h
WebCore/bindings/js/kjs_events.cpp
WebCore/bindings/js/kjs_events.h
WebCore/bindings/js/kjs_navigator.cpp
WebCore/bindings/js/kjs_navigator.h
WebCore/bindings/js/kjs_window.cpp
WebCore/bindings/js/kjs_window.h
WebCore/bindings/scripts/CodeGeneratorJS.pm

index 171fbadb52ca1a6a37a5265e5c9e78fcbed9a28c..716dcff715f2075471d9d73c099d0bf1bc850bda 100644 (file)
@@ -1,3 +1,159 @@
+2007-11-08  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Darin.
+
+        Convert JavaScript internal function objects to use one class per
+        function.  This avoids a switch statement inside what used to be
+        the shared function classes and will allow Shark to better analyze
+        the code.
+
+        To make this switch, the value property of the HashEntry was changed
+        to a union of an intptr_t (which is used to continue handle valueGetters)
+        and function pointer which points to a static constructor for the
+        individual new function objects.
+
+        SunSpider claims this is a 0.5% speedup. 
+
+        * kjs/array_object.cpp:
+        (KJS::ArrayPrototype::getOwnPropertySlot):
+        (KJS::getProperty):
+        (KJS::ArrayProtoFuncToString::callAsFunction):
+        (KJS::ArrayProtoFuncToLocaleString::callAsFunction):
+        (KJS::ArrayProtoFuncJoin::callAsFunction):
+        (KJS::ArrayProtoFuncConcat::callAsFunction):
+        (KJS::ArrayProtoFuncPop::callAsFunction):
+        (KJS::ArrayProtoFuncPush::callAsFunction):
+        (KJS::ArrayProtoFuncReverse::callAsFunction):
+        (KJS::ArrayProtoFuncShift::callAsFunction):
+        (KJS::ArrayProtoFuncSlice::callAsFunction):
+        (KJS::ArrayProtoFuncSort::callAsFunction):
+        (KJS::ArrayProtoFuncSplice::callAsFunction):
+        (KJS::ArrayProtoFuncUnShift::callAsFunction):
+        (KJS::ArrayProtoFuncFilter::callAsFunction):
+        (KJS::ArrayProtoFuncMap::callAsFunction):
+        (KJS::ArrayProtoFuncEvery::callAsFunction):
+        (KJS::ArrayProtoFuncForEach::callAsFunction):
+        (KJS::ArrayProtoFuncSome::callAsFunction):
+        (KJS::ArrayProtoFuncIndexOf::callAsFunction):
+        (KJS::ArrayProtoFuncLastIndexOf::callAsFunction):
+        * kjs/array_object.h:
+        (KJS::ArrayPrototype::classInfo):
+        * kjs/create_hash_table:
+        * kjs/date_object.cpp:
+        (KJS::DatePrototype::getOwnPropertySlot):
+        (KJS::DateProtoFuncToString::callAsFunction):
+        (KJS::DateProtoFuncToUTCString::callAsFunction):
+        (KJS::DateProtoFuncToDateString::callAsFunction):
+        (KJS::DateProtoFuncToTimeString::callAsFunction):
+        (KJS::DateProtoFuncToLocaleString::callAsFunction):
+        (KJS::DateProtoFuncToLocaleDateString::callAsFunction):
+        (KJS::DateProtoFuncToLocaleTimeString::callAsFunction):
+        (KJS::DateProtoFuncValueOf::callAsFunction):
+        (KJS::DateProtoFuncGetTime::callAsFunction):
+        (KJS::DateProtoFuncGetFullYear::callAsFunction):
+        (KJS::DateProtoFuncGetUTCFullYear::callAsFunction):
+        (KJS::DateProtoFuncToGMTString::callAsFunction):
+        (KJS::DateProtoFuncGetMonth::callAsFunction):
+        (KJS::DateProtoFuncGetUTCMonth::callAsFunction):
+        (KJS::DateProtoFuncGetDate::callAsFunction):
+        (KJS::DateProtoFuncGetUTCDate::callAsFunction):
+        (KJS::DateProtoFuncGetDay::callAsFunction):
+        (KJS::DateProtoFuncGetUTCDay::callAsFunction):
+        (KJS::DateProtoFuncGetHours::callAsFunction):
+        (KJS::DateProtoFuncGetUTCHours::callAsFunction):
+        (KJS::DateProtoFuncGetMinutes::callAsFunction):
+        (KJS::DateProtoFuncGetUTCMinutes::callAsFunction):
+        (KJS::DateProtoFuncGetSeconds::callAsFunction):
+        (KJS::DateProtoFuncGetUTCSeconds::callAsFunction):
+        (KJS::DateProtoFuncGetMilliSeconds::callAsFunction):
+        (KJS::DateProtoFuncGetUTCMilliseconds::callAsFunction):
+        (KJS::DateProtoFuncGetTimezoneOffset::callAsFunction):
+        (KJS::DateProtoFuncSetTime::callAsFunction):
+        (KJS::DateProtoFuncSetMilliSeconds::callAsFunction):
+        (KJS::DateProtoFuncSetUTCMilliseconds::callAsFunction):
+        (KJS::DateProtoFuncSetSeconds::callAsFunction):
+        (KJS::DateProtoFuncSetUTCSeconds::callAsFunction):
+        (KJS::DateProtoFuncSetMinutes::callAsFunction):
+        (KJS::DateProtoFuncSetUTCMinutes::callAsFunction):
+        (KJS::DateProtoFuncSetHours::callAsFunction):
+        (KJS::DateProtoFuncSetUTCHours::callAsFunction):
+        (KJS::DateProtoFuncSetDate::callAsFunction):
+        (KJS::DateProtoFuncSetUTCDate::callAsFunction):
+        (KJS::DateProtoFuncSetMonth::callAsFunction):
+        (KJS::DateProtoFuncSetUTCMonth::callAsFunction):
+        (KJS::DateProtoFuncSetFullYear::callAsFunction):
+        (KJS::DateProtoFuncSetUTCFullYear::callAsFunction):
+        (KJS::DateProtoFuncSetYear::callAsFunction):
+        (KJS::DateProtoFuncGetYear::callAsFunction):
+        * kjs/date_object.h:
+        * kjs/lookup.cpp:
+        (KJS::Lookup::find):
+        * kjs/lookup.h:
+        (KJS::HashEntry::):
+        (KJS::staticFunctionGetter):
+        (KJS::staticValueGetter):
+        (KJS::getStaticPropertySlot):
+        (KJS::getStaticFunctionSlot):
+        (KJS::lookupPut):
+        * kjs/math_object.cpp:
+        (KJS::MathObjectImp::getOwnPropertySlot):
+        (KJS::MathProtoFuncAbs::callAsFunction):
+        (KJS::MathProtoFuncACos::callAsFunction):
+        (KJS::MathProtoFuncASin::callAsFunction):
+        (KJS::MathProtoFuncATan::callAsFunction):
+        (KJS::MathProtoFuncATan2::callAsFunction):
+        (KJS::MathProtoFuncCeil::callAsFunction):
+        (KJS::MathProtoFuncCos::callAsFunction):
+        (KJS::MathProtoFuncExp::callAsFunction):
+        (KJS::MathProtoFuncFloor::callAsFunction):
+        (KJS::MathProtoFuncLog::callAsFunction):
+        (KJS::MathProtoFuncMax::callAsFunction):
+        (KJS::MathProtoFuncMin::callAsFunction):
+        (KJS::MathProtoFuncPow::callAsFunction):
+        (KJS::MathProtoFuncRandom::callAsFunction):
+        (KJS::MathProtoFuncRound::callAsFunction):
+        (KJS::MathProtoFuncSin::callAsFunction):
+        (KJS::MathProtoFuncSqrt::callAsFunction):
+        (KJS::MathProtoFuncTan::callAsFunction):
+        * kjs/math_object.h:
+        (KJS::MathObjectImp::classInfo):
+        (KJS::MathObjectImp::):
+        * kjs/string_object.cpp:
+        (KJS::StringPrototype::getOwnPropertySlot):
+        (KJS::StringProtoFuncToString::callAsFunction):
+        (KJS::StringProtoFuncValueOf::callAsFunction):
+        (KJS::StringProtoFuncCharAt::callAsFunction):
+        (KJS::StringProtoFuncCharCodeAt::callAsFunction):
+        (KJS::StringProtoFuncConcat::callAsFunction):
+        (KJS::StringProtoFuncIndexOf::callAsFunction):
+        (KJS::StringProtoFuncLastIndexOf::callAsFunction):
+        (KJS::StringProtoFuncMatch::callAsFunction):
+        (KJS::StringProtoFuncSearch::callAsFunction):
+        (KJS::StringProtoFuncReplace::callAsFunction):
+        (KJS::StringProtoFuncSlice::callAsFunction):
+        (KJS::StringProtoFuncSplit::callAsFunction):
+        (KJS::StringProtoFuncSubstr::callAsFunction):
+        (KJS::StringProtoFuncSubstring::callAsFunction):
+        (KJS::StringProtoFuncToLowerCase::callAsFunction):
+        (KJS::StringProtoFuncToUpperCase::callAsFunction):
+        (KJS::StringProtoFuncToLocaleLowerCase::callAsFunction):
+        (KJS::StringProtoFuncToLocaleUpperCase::callAsFunction):
+        (KJS::StringProtoFuncLocaleCompare::callAsFunction):
+        (KJS::StringProtoFuncBig::callAsFunction):
+        (KJS::StringProtoFuncSmall::callAsFunction):
+        (KJS::StringProtoFuncBlink::callAsFunction):
+        (KJS::StringProtoFuncBold::callAsFunction):
+        (KJS::StringProtoFuncFixed::callAsFunction):
+        (KJS::StringProtoFuncItalics::callAsFunction):
+        (KJS::StringProtoFuncStrike::callAsFunction):
+        (KJS::StringProtoFuncSub::callAsFunction):
+        (KJS::StringProtoFuncSup::callAsFunction):
+        (KJS::StringProtoFuncFontcolor::callAsFunction):
+        (KJS::StringProtoFuncFontsize::callAsFunction):
+        (KJS::StringProtoFuncAnchor::callAsFunction):
+        (KJS::StringProtoFuncLink::callAsFunction):
+        * kjs/string_object.h:
+
 2007-11-08  Adam Roben  <aroben@apple.com>
 
         Windows build fix
index 25e4eb3e240d4f2a381c199904250c106bc4a729..b85d3ad71eca53722f663c75699c392d2e37960c 100644 (file)
@@ -40,25 +40,25 @@ const ClassInfo ArrayPrototype::info = {"Array", &ArrayInstance::info, &arrayTab
 
 /* Source for array_object.lut.h
 @begin arrayTable 16
-  toString       ArrayProtoFunc::ToString       DontEnum|Function 0
-  toLocaleString ArrayProtoFunc::ToLocaleString DontEnum|Function 0
-  concat         ArrayProtoFunc::Concat         DontEnum|Function 1
-  join           ArrayProtoFunc::Join           DontEnum|Function 1
-  pop            ArrayProtoFunc::Pop            DontEnum|Function 0
-  push           ArrayProtoFunc::Push           DontEnum|Function 1
-  reverse        ArrayProtoFunc::Reverse        DontEnum|Function 0
-  shift          ArrayProtoFunc::Shift          DontEnum|Function 0
-  slice          ArrayProtoFunc::Slice          DontEnum|Function 2
-  sort           ArrayProtoFunc::Sort           DontEnum|Function 1
-  splice         ArrayProtoFunc::Splice         DontEnum|Function 2
-  unshift        ArrayProtoFunc::UnShift        DontEnum|Function 1
-  every          ArrayProtoFunc::Every          DontEnum|Function 1
-  forEach        ArrayProtoFunc::ForEach        DontEnum|Function 1
-  some           ArrayProtoFunc::Some           DontEnum|Function 1
-  indexOf        ArrayProtoFunc::IndexOf        DontEnum|Function 1
-  lastIndexOf    ArrayProtoFunc::LastIndexOf    DontEnum|Function 1
-  filter         ArrayProtoFunc::Filter         DontEnum|Function 1
-  map            ArrayProtoFunc::Map            DontEnum|Function 1
+  toString       &ArrayProtoFuncToString::create       DontEnum|Function 0
+  toLocaleString &ArrayProtoFuncToLocaleString::create DontEnum|Function 0
+  concat         &ArrayProtoFuncConcat::create         DontEnum|Function 1
+  join           &ArrayProtoFuncJoin::create           DontEnum|Function 1
+  pop            &ArrayProtoFuncPop::create            DontEnum|Function 0
+  push           &ArrayProtoFuncPush::create           DontEnum|Function 1
+  reverse        &ArrayProtoFuncReverse::create        DontEnum|Function 0
+  shift          &ArrayProtoFuncShift::create          DontEnum|Function 0
+  slice          &ArrayProtoFuncSlice::create          DontEnum|Function 2
+  sort           &ArrayProtoFuncSort::create           DontEnum|Function 1
+  splice         &ArrayProtoFuncSplice::create         DontEnum|Function 2
+  unshift        &ArrayProtoFuncUnShift::create        DontEnum|Function 1
+  every          &ArrayProtoFuncEvery::create          DontEnum|Function 1
+  forEach        &ArrayProtoFuncForEach::create        DontEnum|Function 1
+  some           &ArrayProtoFuncSome::create           DontEnum|Function 1
+  indexOf        &ArrayProtoFuncIndexOf::create        DontEnum|Function 1
+  lastIndexOf    &ArrayProtoFuncLastIndexOf::create    DontEnum|Function 1
+  filter         &ArrayProtoFuncFilter::create         DontEnum|Function 1
+  map            &ArrayProtoFuncMap::create            DontEnum|Function 1
 @end
 */
 
@@ -70,43 +70,68 @@ ArrayPrototype::ArrayPrototype(ExecState*, ObjectPrototype* objProto)
 
 bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return getStaticFunctionSlot<ArrayProtoFunc, ArrayInstance>(exec, &arrayTable, this, propertyName, slot);
+  return getStaticFunctionSlot<ArrayInstance>(exec, &arrayTable, this, propertyName, slot);
 }
 
-// ------------------------------ ArrayProtoFunc ----------------------------
 
-ArrayProtoFunc::ArrayProtoFunc(ExecState* exec, int i, int len, const Identifier& name)
-  : InternalFunctionImp(static_cast<FunctionPrototype*>
-                        (exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
-  , id(i)
-{
-  put(exec, exec->propertyNames().length, jsNumber(len), DontDelete | ReadOnly | DontEnum);
-}
+// ------------------------------ Array Functions ----------------------------
 
-static JSValue *getProperty(ExecState *exec, JSObject *obj, unsigned index)
+// Helper function
+static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index)
 {
     PropertySlot slot;
     if (!obj->getPropertySlot(exec, index, slot))
-        return NULL;
+        return 0;
     return slot.getValue(exec, obj, index);
 }
 
-// ECMA 15.4.4
-JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+JSValue* ArrayProtoFuncToString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
 {
-  unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+    if (!thisObj->inherits(&ArrayInstance::info))
+        return throwError(exec, TypeError);
+
+    static HashSet<JSObject*> visitedElems;
+    static const UString* empty = new UString("");
+    static const UString* comma = new UString(",");
+    bool alreadyVisited = !visitedElems.add(thisObj).second;
+    if (alreadyVisited)
+        return jsString(*empty);
+    UString separator = *comma;
+    UString str = *empty;
+
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+    for (unsigned int k = 0; k < length; k++) {
+        if (k >= 1)
+            str += separator;
+        if (str.isNull()) {
+            JSObject *error = Error::create(exec, GeneralError, "Out of memory");
+            exec->setException(error);
+            break;
+        }
+
+        JSValue* element = thisObj->get(exec, k);
+        if (element->isUndefinedOrNull())
+            continue;
+
+        str += element->toString(exec);
 
-  JSValue *result = 0; // work around gcc 4.0 bug in uninitialized variable warning
-  
-  switch (id) {
-  case ToLocaleString:
-  case ToString:
+        if (str.isNull()) {
+            JSObject *error = Error::create(exec, GeneralError, "Out of memory");
+            exec->setException(error);
+        }
+
+        if (exec->hadException())
+            break;
+    }
+    visitedElems.remove(thisObj);
+    return jsString(str);
+}
 
+JSValue* ArrayProtoFuncToLocaleString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
     if (!thisObj->inherits(&ArrayInstance::info))
-      return throwError(exec, TypeError);
+        return throwError(exec, TypeError);
 
-    // fall through
-  case Join: {
     static HashSet<JSObject*> visitedElems;
     static const UString* empty = new UString("");
     static const UString* comma = new UString(",");
@@ -116,8 +141,7 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
     UString separator = *comma;
     UString str = *empty;
 
-    if (id == Join && !args[0]->isUndefined())
-        separator = args[0]->toString(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     for (unsigned int k = 0; k < length; k++) {
         if (k >= 1)
             str += separator;
@@ -132,19 +156,17 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
             continue;
 
         bool fallback = false;
-        if (id == ToLocaleString) {
-            JSObject* o = element->toObject(exec);
-            JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
-            if (conversionFunction->isObject() && static_cast<JSObject*>(conversionFunction)->implementsCall()) {
-                List args;
-                str += static_cast<JSObject*>(conversionFunction)->call(exec, o, args)->toString(exec);
-            } else {
-                // try toString() fallback
-                fallback = true;
-            }
+        JSObject* o = element->toObject(exec);
+        JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
+        if (conversionFunction->isObject() && static_cast<JSObject*>(conversionFunction)->implementsCall()) {
+            List args;
+            str += static_cast<JSObject*>(conversionFunction)->call(exec, o, args)->toString(exec);
+        } else {
+            // try toString() fallback
+            fallback = true;
         }
 
-        if (id == ToString || id == Join || fallback)
+        if (fallback)
             str += element->toString(exec);
 
         if (str.isNull()) {
@@ -156,45 +178,91 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
             break;
     }
     visitedElems.remove(thisObj);
-    result = jsString(str);
-    break;
-  }
-  case Concat: {
-    JSObject *arr = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty()));
+    return jsString(str);
+}
+
+JSValue* ArrayProtoFuncJoin::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    static HashSet<JSObject*> visitedElems;
+    static const UString* empty = new UString("");
+    static const UString* comma = new UString(",");
+    bool alreadyVisited = !visitedElems.add(thisObj).second;
+    if (alreadyVisited)
+        return jsString(*empty);
+    UString separator = *comma;
+    UString str = *empty;
+
+    if (!args[0]->isUndefined())
+        separator = args[0]->toString(exec);
+
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+    for (unsigned int k = 0; k < length; k++) {
+        if (k >= 1)
+            str += separator;
+        if (str.isNull()) {
+            JSObject *error = Error::create(exec, GeneralError, "Out of memory");
+            exec->setException(error);
+            break;
+        }
+
+        JSValue* element = thisObj->get(exec, k);
+        if (element->isUndefinedOrNull())
+            continue;
+
+        str += element->toString(exec);
+
+        if (str.isNull()) {
+            JSObject *error = Error::create(exec, GeneralError, "Out of memory");
+            exec->setException(error);
+        }
+
+        if (exec->hadException())
+            break;
+    }
+    visitedElems.remove(thisObj);
+    return jsString(str);
+}
+
+JSValue* ArrayProtoFuncConcat::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    JSObject* arr = static_cast<JSObject*>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty()));
     int n = 0;
     JSValue *curArg = thisObj;
     JSObject *curObj = static_cast<JSObject *>(thisObj);
     List::const_iterator it = args.begin();
     List::const_iterator end = args.end();
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     for (;;) {
-      if (curArg->isObject() &&
-          curObj->inherits(&ArrayInstance::info)) {
-        unsigned int k = 0;
-        // Older versions tried to optimize out getting the length of thisObj
-        // by checking for n != 0, but that doesn't work if thisObj is an empty array.
-        length = curObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
-        while (k < length) {
-          if (JSValue *v = getProperty(exec, curObj, k))
-            arr->put(exec, n, v);
-          n++;
-          k++;
+        if (curArg->isObject() &&
+            curObj->inherits(&ArrayInstance::info)) {
+            unsigned int k = 0;
+            // Older versions tried to optimize out getting the length of thisObj
+            // by checking for n != 0, but that doesn't work if thisObj is an empty array.
+            length = curObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+            while (k < length) {
+                if (JSValue *v = getProperty(exec, curObj, k))
+                    arr->put(exec, n, v);
+                n++;
+                k++;
+            }
+        } else {
+            arr->put(exec, n, curArg);
+            n++;
         }
-      } else {
-        arr->put(exec, n, curArg);
-        n++;
-      }
-      if (it == end)
-        break;
-      curArg = *it;
-      curObj = static_cast<JSObject*>(curArg); // may be 0
-      ++it;
+        if (it == end)
+            break;
+        curArg = *it;
+        curObj = static_cast<JSObject*>(curArg); // may be 0
+        ++it;
     }
     arr->put(exec, exec->propertyNames().length, jsNumber(n), DontEnum | DontDelete);
+    return arr;
+}
 
-    result = arr;
-    break;
-  }
-  case Pop:{
+JSValue* ArrayProtoFuncPop::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    JSValue* result = 0;
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     if (length == 0) {
       thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete);
       result = jsUndefined();
@@ -202,39 +270,47 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
       result = thisObj->get(exec, length - 1);
       thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete);
     }
-    break;
-  }
-  case Push: {
+    return result;
+}
+
+JSValue* ArrayProtoFuncPush::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     for (unsigned int n = 0; n < args.size(); n++)
-      thisObj->put(exec, length + n, args[n]);
+        thisObj->put(exec, length + n, args[n]);
     length += args.size();
     thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete);
-    result = jsNumber(length);
-    break;
-  }
-  case Reverse: {
+    return jsNumber(length);
+}
 
+JSValue* ArrayProtoFuncReverse::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     unsigned int middle = length / 2;
 
     for (unsigned int k = 0; k < middle; k++) {
-      unsigned lk1 = length - k - 1;
-      JSValue *obj2 = getProperty(exec, thisObj, lk1);
-      JSValue *obj = getProperty(exec, thisObj, k);
+        unsigned lk1 = length - k - 1;
+        JSValue *obj2 = getProperty(exec, thisObj, lk1);
+        JSValue *obj = getProperty(exec, thisObj, k);
 
-      if (obj2) 
-        thisObj->put(exec, k, obj2);
-      else
-        thisObj->deleteProperty(exec, k);
+        if (obj2) 
+            thisObj->put(exec, k, obj2);
+        else
+            thisObj->deleteProperty(exec, k);
 
-      if (obj)
-        thisObj->put(exec, lk1, obj);
-      else
-        thisObj->deleteProperty(exec, lk1);
+        if (obj)
+            thisObj->put(exec, lk1, obj);
+        else
+            thisObj->deleteProperty(exec, lk1);
     }
-    result = thisObj;
-    break;
-  }
-  case Shift: {
+    return thisObj;
+}
+
+JSValue* ArrayProtoFuncShift::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    JSValue* result = 0;
+
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     if (length == 0) {
       thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete);
       result = jsUndefined();
@@ -249,49 +325,54 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
       thisObj->deleteProperty(exec, length - 1);
       thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete);
     }
-    break;
-  }
-  case Slice: {
+    return result;
+}
+
+JSValue* ArrayProtoFuncSlice::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
     // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
 
     // We return a new array
     JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty()));
-    result = resObj;
+    JSValue* result = resObj;
     double begin = args[0]->toInteger(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     if (begin >= 0) {
-      if (begin > length)
-        begin = length;
+        if (begin > length)
+            begin = length;
     } else {
-      begin += length;
-      if (begin < 0)
-        begin = 0;
+        begin += length;
+        if (begin < 0)
+            begin = 0;
     }
     double end;
     if (args[1]->isUndefined())
-      end = length;
+        end = length;
     else {
-      end = args[1]->toInteger(exec);
-      if (end < 0) {
-        end += length;
-        if (end < 0)
-          end = 0;
-      } else {
-        if (end > length)
-          end = length;
-      }
+        end = args[1]->toInteger(exec);
+        if (end < 0) {
+            end += length;
+            if (end < 0)
+                end = 0;
+        } else {
+            if (end > length)
+                end = length;
+        }
     }
 
     int n = 0;
     int b = static_cast<int>(begin);
     int e = static_cast<int>(end);
     for(int k = b; k < e; k++, n++) {
-      if (JSValue *v = getProperty(exec, thisObj, k))
-        resObj->put(exec, n, v);
+        if (JSValue *v = getProperty(exec, thisObj, k))
+            resObj->put(exec, n, v);
     }
     resObj->put(exec, exec->propertyNames().length, jsNumber(n), DontEnum | DontDelete);
-    break;
-  }
-  case Sort:{
+    return result;
+}
+
+JSValue* ArrayProtoFuncSort::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
 #if 0
     printf("KJS Array::Sort length=%d\n", length);
     for ( unsigned int i = 0 ; i<length ; ++i )
@@ -310,14 +391,14 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
         ((ArrayInstance *)thisObj)->sort(exec, sortFunction);
       else
         ((ArrayInstance *)thisObj)->sort(exec);
-      result = thisObj;
-      break;
+      return thisObj;
     }
 
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+
     if (length == 0) {
       thisObj->put(exec, exec->propertyNames().length, jsNumber(0), DontEnum | DontDelete);
-      result = thisObj;
-      break;
+      return thisObj;
     }
 
     // "Min" sort. Not the fastest, but definitely less code than heapsort
@@ -356,19 +437,21 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
             thisObj->put( exec, i, minObj );
             thisObj->put( exec, themin, iObj );
           }
-      }
+    }
 #if 0
     printf("KJS Array::Sort -- Resulting array:\n");
     for ( unsigned int i = 0 ; i<length ; ++i )
       printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii() );
 #endif
-    result = thisObj;
-    break;
-  }
-  case Splice: {
+    return thisObj;
+}
+
+JSValue* ArrayProtoFuncSplice::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
     // 15.4.4.12 - oh boy this is huge
-    JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty()));
-    result = resObj;
+    JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty()));
+    JSValue* result = resObj;
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     int begin = args[0]->toUInt32(exec);
     if ( begin < 0 )
       begin = maxInt( begin + length, 0 );
@@ -414,9 +497,13 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
       thisObj->put(exec, k+begin, args[k+2]);
     }
     thisObj->put(exec, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs), DontEnum | DontDelete);
-    break;
-  }
-  case UnShift: { // 15.4.4.13
+    return result;
+}
+
+JSValue* ArrayProtoFuncUnShift::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // 15.4.4.13
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     unsigned int nrArgs = args.size();
     for ( unsigned int k = length; k > 0; --k )
     {
@@ -427,105 +514,184 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
     }
     for ( unsigned int k = 0; k < nrArgs; ++k )
       thisObj->put(exec, k, args[k]);
-    result = jsNumber(length + nrArgs);
+    JSValue* result = jsNumber(length + nrArgs);
     thisObj->put(exec, exec->propertyNames().length, result, DontEnum | DontDelete);
-    break;
-  }
-  case Filter:
-  case Map: {
-    JSObject *eachFunction = args[0]->toObject(exec);
+    return result;
+}
+
+JSValue* ArrayProtoFuncFilter::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    JSObject* eachFunction = args[0]->toObject(exec);
     
     if (!eachFunction->implementsCall())
-      return throwError(exec, TypeError);
+        return throwError(exec, TypeError);
     
     JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() :  args[1]->toObject(exec);
-    JSObject *resultArray;
-    
-    if (id == Filter) 
-      resultArray = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty()));
-    else {
-      List args;
-      args.append(jsNumber(length));
-      resultArray = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, args));
-    }
-    
+    JSObject *resultArray = static_cast<JSObject*>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty()));
+
     unsigned filterIndex = 0;
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
-      PropertySlot slot;
+        PropertySlot slot;
 
-      if (!thisObj->getPropertySlot(exec, k, slot))
-         continue;
+        if (!thisObj->getPropertySlot(exec, k, slot))
+            continue;
         
-      JSValue *v = slot.getValue(exec, thisObj, k);
-      
-      List eachArguments;
-      
-      eachArguments.append(v);
-      eachArguments.append(jsNumber(k));
-      eachArguments.append(thisObj);
+        JSValue *v = slot.getValue(exec, thisObj, k);
+        
+        List eachArguments;
+        
+        eachArguments.append(v);
+        eachArguments.append(jsNumber(k));
+        eachArguments.append(thisObj);
       
-      JSValue *result = eachFunction->call(exec, applyThis, eachArguments);
+        JSValue *result = eachFunction->call(exec, applyThis, eachArguments);
       
-      if (id == Map)
-        resultArray->put(exec, k, result);
-      else if (result->toBoolean(exec)) 
-        resultArray->put(exec, filterIndex++, v);
+        if (result->toBoolean(exec)) 
+            resultArray->put(exec, filterIndex++, v);
     }
-    
     return resultArray;
-  }
-  case Every:
-  case ForEach:
-  case Some: {
-    //Documentation for these three is available at:
-    //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
-    //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
-    //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
+}
+
+JSValue* ArrayProtoFuncMap::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    JSObject* eachFunction = args[0]->toObject(exec);
+    if (!eachFunction->implementsCall())
+        return throwError(exec, TypeError);
     
+    JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() :  args[1]->toObject(exec);
+
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+
+    List mapArgs;
+    mapArgs.append(jsNumber(length));
+    JSObject* resultArray = static_cast<JSObject*>(exec->lexicalInterpreter()->builtinArray()->construct(exec, mapArgs));
+
+    for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+        PropertySlot slot;
+        if (!thisObj->getPropertySlot(exec, k, slot))
+            continue;
+
+        JSValue *v = slot.getValue(exec, thisObj, k);
+
+        List eachArguments;
+
+        eachArguments.append(v);
+        eachArguments.append(jsNumber(k));
+        eachArguments.append(thisObj);
+
+        JSValue *result = eachFunction->call(exec, applyThis, eachArguments);
+        resultArray->put(exec, k, result);
+    }
+
+    return resultArray;
+}
+
+// Documentation for these three is available at:
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
+
+JSValue* ArrayProtoFuncEvery::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
     JSObject *eachFunction = args[0]->toObject(exec);
     
     if (!eachFunction->implementsCall())
-      return throwError(exec, TypeError);
+        return throwError(exec, TypeError);
     
     JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() :  args[1]->toObject(exec);
     
-    if (id == Some || id == Every)
-      result = jsBoolean(id == Every);
-    else
-      result = jsUndefined();
+    JSValue* result = jsBoolean(true);
     
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
-      PropertySlot slot;
-        
-      if (!thisObj->getPropertySlot(exec, k, slot))
-        continue;
-      
-      List eachArguments;
+        PropertySlot slot;
+          
+        if (!thisObj->getPropertySlot(exec, k, slot))
+            continue;
       
-      eachArguments.append(slot.getValue(exec, thisObj, k));
-      eachArguments.append(jsNumber(k));
-      eachArguments.append(thisObj);
+        List eachArguments;
+        
+        eachArguments.append(slot.getValue(exec, thisObj, k));
+        eachArguments.append(jsNumber(k));
+        eachArguments.append(thisObj);
       
-      bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec);
+        bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec);
       
-      if (id == Every && !predicateResult) {
-        result = jsBoolean(false);
-        break;
-      }
-      if (id == Some && predicateResult) {
-        result = jsBoolean(true);
-        break;
-      }
+        if (!predicateResult) {
+            result = jsBoolean(false);
+            break;
+        }
     }
-    break;
-  }
 
-  case IndexOf: {
+    return result;
+}
+
+JSValue* ArrayProtoFuncForEach::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    JSObject* eachFunction = args[0]->toObject(exec);
+
+    if (!eachFunction->implementsCall())
+        return throwError(exec, TypeError);
+
+    JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() :  args[1]->toObject(exec);
+
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+    for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+        PropertySlot slot;
+        if (!thisObj->getPropertySlot(exec, k, slot))
+            continue;
+
+        List eachArguments;
+        eachArguments.append(slot.getValue(exec, thisObj, k));
+        eachArguments.append(jsNumber(k));
+        eachArguments.append(thisObj);
+
+        eachFunction->call(exec, applyThis, eachArguments);
+    }
+    return jsUndefined();
+}
+
+JSValue* ArrayProtoFuncSome::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    JSObject* eachFunction = args[0]->toObject(exec);
+
+    if (!eachFunction->implementsCall())
+        return throwError(exec, TypeError);
+
+    JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() :  args[1]->toObject(exec);
+
+    JSValue* result = jsBoolean(false);
+
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+    for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+        PropertySlot slot;
+        if (!thisObj->getPropertySlot(exec, k, slot))
+            continue;
+
+        List eachArguments;
+        eachArguments.append(slot.getValue(exec, thisObj, k));
+        eachArguments.append(jsNumber(k));
+        eachArguments.append(thisObj);
+
+        bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec);
+
+        if (predicateResult) {
+            result = jsBoolean(true);
+            break;
+        }
+    }
+    return result;
+}
+
+JSValue* ArrayProtoFuncIndexOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
     // JavaScript 1.5 Extension by Mozilla
     // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
 
     unsigned index = 0;
     double d = args[1]->toInteger(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     if (d < 0)
         d += length;
     if (d > 0) {
@@ -545,11 +711,14 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
     }
 
     return jsNumber(-1);
-  }
-  case LastIndexOf: {
-       // JavaScript 1.6 Extension by Mozilla
-      // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf 
+}
+
+JSValue* ArrayProtoFuncLastIndexOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // JavaScript 1.6 Extension by Mozilla
+    // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf 
 
+    unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
     int index = length - 1;
     double d = args[1]->toIntegerPreserveNaN(exec);
 
@@ -572,13 +741,6 @@ JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, cons
           
     return jsNumber(-1);
 }
-  default:
-    ASSERT(0);
-    result = 0;
-    break;
-  }
-  return result;
-}
 
 // ------------------------------ ArrayObjectImp -------------------------------
 
index f2ef7818faea10f5e3b4bc86200e5d1f2272b6e1..99a3a00cb9181fef81790cbb1d684d755d99ba57 100644 (file)
@@ -2,6 +2,7 @@
 /*
  *  This file is part of the KDE libraries
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 
 #include "array_instance.h"
 #include "function_object.h"
+#include "lookup.h"
 
 namespace KJS {
 
  class ArrayPrototype : public ArrayInstance {
   public:
-    ArrayPrototype(ExecState *exec,
-                      ObjectPrototype *objProto);
-    bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
-    virtual const ClassInfo *classInfo() const { return &info; }
-    static const ClassInfo info;
-  };
-
-  class ArrayProtoFunc : public InternalFunctionImp {
-  public:
-    ArrayProtoFunc(ExecState *exec, int i, int len, const Identifier& name);
+    ArrayPrototype(ExecState*, ObjectPrototype*);
 
-    virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-
-    enum { ToString, ToLocaleString, Concat, Join, Pop, Push,
-          Reverse, Shift, Slice, Sort, Splice, UnShift, 
-          Every, ForEach, Some, IndexOf, Filter, Map, LastIndexOf };
-  private:
-    int id;
+    bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+    virtual const ClassInfo* classInfo() const { return &info; }
+    static const ClassInfo info;
   };
 
   class ArrayObjectImp : public InternalFunctionImp {
   public:
-    ArrayObjectImp(ExecState *exec,
-                   FunctionPrototype *funcProto,
-                   ArrayPrototype *arrayProto);
+    ArrayObjectImp(ExecState*, FunctionPrototype*, ArrayPrototype*);
 
     virtual bool implementsConstruct() const;
-    virtual JSObject *construct(ExecState *exec, const List &args);
-    virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+    virtual JSObject* construct(ExecState*, const List&);
+    virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
 
   };
 
-} // namespace
+#define FOR_EACH_CLASS(macro) \
+    macro(ArrayProtoFuncToString) \
+    macro(ArrayProtoFuncToLocaleString) \
+    macro(ArrayProtoFuncConcat) \
+    macro(ArrayProtoFuncJoin) \
+    macro(ArrayProtoFuncPop) \
+    macro(ArrayProtoFuncPush) \
+    macro(ArrayProtoFuncReverse) \
+    macro(ArrayProtoFuncShift) \
+    macro(ArrayProtoFuncSlice) \
+    macro(ArrayProtoFuncSort) \
+    macro(ArrayProtoFuncSplice) \
+    macro(ArrayProtoFuncUnShift) \
+    macro(ArrayProtoFuncEvery) \
+    macro(ArrayProtoFuncForEach) \
+    macro(ArrayProtoFuncSome) \
+    macro(ArrayProtoFuncIndexOf) \
+    macro(ArrayProtoFuncFilter) \
+    macro(ArrayProtoFuncMap) \
+    macro(ArrayProtoFuncLastIndexOf) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
+} // namespace KJS
 
-#endif
+#endif // ARRAY_OBJECT_H_
index d508893982f2faee7cd131ae63b71a13e0191fb0..6800722a2b1dccf84aed8c71b8047c7129d175cd 100755 (executable)
@@ -225,7 +225,7 @@ sub output() {
       if (defined($entry)) {
         my $key = $keys[$entry];
         print "   \{ \"" . $key . "\"";
-        print ", " . $values[$entry];
+        print ", { (intptr_t)" . $values[$entry] . " }";
         print ", " . $attrs[$entry];
         print ", " . $params[$entry];
         print ", ";
@@ -236,7 +236,7 @@ sub output() {
         }
         print "/* " . $hashes[$entry] . " */ ";
       } else {
-        print "   { 0, 0, 0, 0, 0 }";
+        print "   { 0, { 0 }, 0, 0, 0 }";
       }    
       print "," unless ($i == $size - 1);
       print "\n";
index ec5d1edba7da3e4a8a0cbe1b60173e55cb1f56fc..a00a384e45df6b4d90881242f60107fb9f7a634d 100644 (file)
@@ -373,52 +373,52 @@ static inline bool isTime_tSigned()
 const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, &dateTable};
 
 /* Source for date_object.lut.h
-   We use a negative ID to denote the "UTC" variant.
+   FIXMEL We could use templates to simplify the UTC variants.
 @begin dateTable 61
-  toString              DateProtoFunc::ToString                 DontEnum|Function       0
-  toUTCString           -DateProtoFunc::ToUTCString             DontEnum|Function       0
-  toDateString          DateProtoFunc::ToDateString             DontEnum|Function       0
-  toTimeString          DateProtoFunc::ToTimeString             DontEnum|Function       0
-  toLocaleString        DateProtoFunc::ToLocaleString           DontEnum|Function       0
-  toLocaleDateString    DateProtoFunc::ToLocaleDateString       DontEnum|Function       0
-  toLocaleTimeString    DateProtoFunc::ToLocaleTimeString       DontEnum|Function       0
-  valueOf               DateProtoFunc::ValueOf                  DontEnum|Function       0
-  getTime               DateProtoFunc::GetTime                  DontEnum|Function       0
-  getFullYear           DateProtoFunc::GetFullYear              DontEnum|Function       0
-  getUTCFullYear        -DateProtoFunc::GetFullYear             DontEnum|Function       0
-  toGMTString           -DateProtoFunc::ToGMTString             DontEnum|Function       0
-  getMonth              DateProtoFunc::GetMonth                 DontEnum|Function       0
-  getUTCMonth           -DateProtoFunc::GetMonth                DontEnum|Function       0
-  getDate               DateProtoFunc::GetDate                  DontEnum|Function       0
-  getUTCDate            -DateProtoFunc::GetDate                 DontEnum|Function       0
-  getDay                DateProtoFunc::GetDay                   DontEnum|Function       0
-  getUTCDay             -DateProtoFunc::GetDay                  DontEnum|Function       0
-  getHours              DateProtoFunc::GetHours                 DontEnum|Function       0
-  getUTCHours           -DateProtoFunc::GetHours                DontEnum|Function       0
-  getMinutes            DateProtoFunc::GetMinutes               DontEnum|Function       0
-  getUTCMinutes         -DateProtoFunc::GetMinutes              DontEnum|Function       0
-  getSeconds            DateProtoFunc::GetSeconds               DontEnum|Function       0
-  getUTCSeconds         -DateProtoFunc::GetSeconds              DontEnum|Function       0
-  getMilliseconds       DateProtoFunc::GetMilliSeconds          DontEnum|Function       0
-  getUTCMilliseconds    -DateProtoFunc::GetMilliSeconds         DontEnum|Function       0
-  getTimezoneOffset     DateProtoFunc::GetTimezoneOffset        DontEnum|Function       0
-  setTime               DateProtoFunc::SetTime                  DontEnum|Function       1
-  setMilliseconds       DateProtoFunc::SetMilliSeconds          DontEnum|Function       1
-  setUTCMilliseconds    -DateProtoFunc::SetMilliSeconds         DontEnum|Function       1
-  setSeconds            DateProtoFunc::SetSeconds               DontEnum|Function       2
-  setUTCSeconds         -DateProtoFunc::SetSeconds              DontEnum|Function       2
-  setMinutes            DateProtoFunc::SetMinutes               DontEnum|Function       3
-  setUTCMinutes         -DateProtoFunc::SetMinutes              DontEnum|Function       3
-  setHours              DateProtoFunc::SetHours                 DontEnum|Function       4
-  setUTCHours           -DateProtoFunc::SetHours                DontEnum|Function       4
-  setDate               DateProtoFunc::SetDate                  DontEnum|Function       1
-  setUTCDate            -DateProtoFunc::SetDate                 DontEnum|Function       1
-  setMonth              DateProtoFunc::SetMonth                 DontEnum|Function       2
-  setUTCMonth           -DateProtoFunc::SetMonth                DontEnum|Function       2
-  setFullYear           DateProtoFunc::SetFullYear              DontEnum|Function       3
-  setUTCFullYear        -DateProtoFunc::SetFullYear             DontEnum|Function       3
-  setYear               DateProtoFunc::SetYear                  DontEnum|Function       1
-  getYear               DateProtoFunc::GetYear                  DontEnum|Function       0
+  toString              &DateProtoFuncToString::create                DontEnum|Function       0
+  toUTCString           &DateProtoFuncToUTCString::create             DontEnum|Function       0
+  toDateString          &DateProtoFuncToDateString::create            DontEnum|Function       0
+  toTimeString          &DateProtoFuncToTimeString::create            DontEnum|Function       0
+  toLocaleString        &DateProtoFuncToLocaleString::create          DontEnum|Function       0
+  toLocaleDateString    &DateProtoFuncToLocaleDateString::create      DontEnum|Function       0
+  toLocaleTimeString    &DateProtoFuncToLocaleTimeString::create      DontEnum|Function       0
+  valueOf               &DateProtoFuncValueOf::create                 DontEnum|Function       0
+  getTime               &DateProtoFuncGetTime::create                 DontEnum|Function       0
+  getFullYear           &DateProtoFuncGetFullYear::create             DontEnum|Function       0
+  getUTCFullYear        &DateProtoFuncGetUTCFullYear::create          DontEnum|Function       0
+  toGMTString           &DateProtoFuncToGMTString::create             DontEnum|Function       0
+  getMonth              &DateProtoFuncGetMonth::create                DontEnum|Function       0
+  getUTCMonth           &DateProtoFuncGetUTCMonth::create             DontEnum|Function       0
+  getDate               &DateProtoFuncGetDate::create                 DontEnum|Function       0
+  getUTCDate            &DateProtoFuncGetUTCDate::create              DontEnum|Function       0
+  getDay                &DateProtoFuncGetDay::create                  DontEnum|Function       0
+  getUTCDay             &DateProtoFuncGetUTCDay::create               DontEnum|Function       0
+  getHours              &DateProtoFuncGetHours::create                DontEnum|Function       0
+  getUTCHours           &DateProtoFuncGetUTCHours::create             DontEnum|Function       0
+  getMinutes            &DateProtoFuncGetMinutes::create              DontEnum|Function       0
+  getUTCMinutes         &DateProtoFuncGetUTCMinutes::create           DontEnum|Function       0
+  getSeconds            &DateProtoFuncGetSeconds::create              DontEnum|Function       0
+  getUTCSeconds         &DateProtoFuncGetUTCSeconds::create           DontEnum|Function       0
+  getMilliseconds       &DateProtoFuncGetMilliSeconds::create         DontEnum|Function       0
+  getUTCMilliseconds    &DateProtoFuncGetUTCMilliseconds::create      DontEnum|Function       0
+  getTimezoneOffset     &DateProtoFuncGetTimezoneOffset::create       DontEnum|Function       0
+  setTime               &DateProtoFuncSetTime::create                 DontEnum|Function       1
+  setMilliseconds       &DateProtoFuncSetMilliSeconds::create         DontEnum|Function       1
+  setUTCMilliseconds    &DateProtoFuncSetUTCMilliseconds::create      DontEnum|Function       1
+  setSeconds            &DateProtoFuncSetSeconds::create              DontEnum|Function       2
+  setUTCSeconds         &DateProtoFuncSetUTCSeconds::create           DontEnum|Function       2
+  setMinutes            &DateProtoFuncSetMinutes::create              DontEnum|Function       3
+  setUTCMinutes         &DateProtoFuncSetUTCMinutes::create           DontEnum|Function       3
+  setHours              &DateProtoFuncSetHours::create                DontEnum|Function       4
+  setUTCHours           &DateProtoFuncSetUTCHours::create             DontEnum|Function       4
+  setDate               &DateProtoFuncSetDate::create                 DontEnum|Function       1
+  setUTCDate            &DateProtoFuncSetUTCDate::create              DontEnum|Function       1
+  setMonth              &DateProtoFuncSetMonth::create                DontEnum|Function       2
+  setUTCMonth           &DateProtoFuncSetUTCMonth::create             DontEnum|Function       2
+  setFullYear           &DateProtoFuncSetFullYear::create             DontEnum|Function       3
+  setUTCFullYear        &DateProtoFuncSetUTCFullYear::create          DontEnum|Function       3
+  setYear               &DateProtoFuncSetYear::create                 DontEnum|Function       1
+  getYear               &DateProtoFuncGetYear::create                 DontEnum|Function       0
 @end
 */
 // ECMA 15.9.4
@@ -432,163 +432,7 @@ DatePrototype::DatePrototype(ExecState *, ObjectPrototype *objectProto)
 
 bool DatePrototype::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    return getStaticFunctionSlot<DateProtoFunc, JSObject>(exec, &dateTable, this, propertyName, slot);
-}
-
-// ------------------------------ DateProtoFunc -----------------------------
-
-DateProtoFunc::DateProtoFunc(ExecState* exec, int i, int len, const Identifier& name)
-  : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
-  , id(abs(i))
-  , utc(i < 0)
-  // We use a negative ID to denote the "UTC" variant.
-{
-    putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
-}
-
-JSValue *DateProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
-{
-  if (!thisObj->inherits(&DateInstance::info))
-    return throwError(exec, TypeError);
-
-  DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
-
-  JSValue *result = 0;
-  UString s;
-  JSValue *v = thisDateObj->internalValue();
-  double milli = v->toNumber(exec);
-  if (isnan(milli)) {
-    switch (id) {
-      case ToString:
-      case ToDateString:
-      case ToTimeString:
-      case ToGMTString:
-      case ToUTCString:
-      case ToLocaleString:
-      case ToLocaleDateString:
-      case ToLocaleTimeString:
-        return jsString("Invalid Date");
-      case ValueOf:
-      case GetTime:
-      case GetYear:
-      case GetFullYear:
-      case GetMonth:
-      case GetDate:
-      case GetDay:
-      case GetHours:
-      case GetMinutes:
-      case GetSeconds:
-      case GetMilliSeconds:
-      case GetTimezoneOffset:
-        return jsNaN();
-    }
-  }
-  
-  double secs = floor(milli / msPerSecond);
-  double ms = milli - secs * msPerSecond;
-
-  GregorianDateTime t;
-  msToGregorianDateTime(milli, utc, t);
-
-  switch (id) {
-  case ToString:
-    return jsString(formatDate(t) + " " + formatTime(t, utc));
-  case ToDateString:
-    return jsString(formatDate(t));
-    break;
-  case ToTimeString:
-    return jsString(formatTime(t, utc));
-    break;
-  case ToGMTString:
-  case ToUTCString:
-    return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
-    break;
-#if PLATFORM(MAC)
-  case ToLocaleString:
-    return jsString(formatLocaleDate(exec, secs, true, true, args));
-    break;
-  case ToLocaleDateString:
-    return jsString(formatLocaleDate(exec, secs, true, false, args));
-    break;
-  case ToLocaleTimeString:
-    return jsString(formatLocaleDate(exec, secs, false, true, args));
-    break;
-#else
-  case ToLocaleString:
-    return formatLocaleDate(t, LocaleDateAndTime);
-    break;
-  case ToLocaleDateString:
-    return formatLocaleDate(t, LocaleDate);
-    break;
-  case ToLocaleTimeString:
-    return formatLocaleDate(t, LocaleTime);
-    break;
-#endif
-  case ValueOf:
-  case GetTime:
-    return jsNumber(milli);
-  case GetYear:
-    // IE returns the full year even in getYear.
-    if (exec->dynamicInterpreter()->compatMode() == Interpreter::IECompat)
-      return jsNumber(1900 + t.year);
-    return jsNumber(t.year);
-  case GetFullYear:
-    return jsNumber(1900 + t.year);
-  case GetMonth:
-    return jsNumber(t.month);
-  case GetDate:
-    return jsNumber(t.monthDay);
-  case GetDay:
-    return jsNumber(t.weekDay);
-  case GetHours:
-    return jsNumber(t.hour);
-  case GetMinutes:
-    return jsNumber(t.minute);
-  case GetSeconds:
-    return jsNumber(t.second);
-  case GetMilliSeconds:
-    return jsNumber(ms);
-  case GetTimezoneOffset:
-    return jsNumber(-gmtoffset(t) / minutesPerHour);
-  case SetTime:
-    milli = timeClip(args[0]->toNumber(exec));
-    result = jsNumber(milli);
-    thisDateObj->setInternalValue(result);
-    break;
-  case SetMilliSeconds:
-    fillStructuresUsingTimeArgs(exec, args, 1, &ms, &t);
-    break;
-  case SetSeconds:
-    fillStructuresUsingTimeArgs(exec, args, 2, &ms, &t);
-    break;
-  case SetMinutes:
-    fillStructuresUsingTimeArgs(exec, args, 3, &ms, &t);
-    break;
-  case SetHours:
-    fillStructuresUsingTimeArgs(exec, args, 4, &ms, &t);
-    break;
-  case SetDate:
-    fillStructuresUsingDateArgs(exec, args, 1, &ms, &t);
-    break;
-  case SetMonth:
-    fillStructuresUsingDateArgs(exec, args, 2, &ms, &t);    
-    break;
-  case SetFullYear:
-    fillStructuresUsingDateArgs(exec, args, 3, &ms, &t);
-    break;
-  case SetYear:
-    t.year = (args[0]->toInt32(exec) > 99 || args[0]->toInt32(exec) < 0) ? args[0]->toInt32(exec) - 1900 : args[0]->toInt32(exec);
-    break;
-  }
-
-  if (id == SetYear || id == SetMilliSeconds || id == SetSeconds ||
-      id == SetMinutes || id == SetHours || id == SetDate ||
-      id == SetMonth || id == SetFullYear ) {
-    result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
-    thisDateObj->setInternalValue(result);
-  }
-  
-  return result;
+    return getStaticFunctionSlot<JSObject>(exec, &dateTable, this, propertyName, slot);
 }
 
 // ------------------------------ DateObjectImp --------------------------------
@@ -1089,4 +933,875 @@ double timeClip(double t)
     return trunc(t);
 }
 
+// Functions
+
+JSValue* DateProtoFuncToString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsString(formatDate(t) + " " + formatTime(t, utc));
+}
+
+JSValue* DateProtoFuncToUTCString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValue* DateProtoFuncToDateString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsString(formatDate(t));
+}
+
+JSValue* DateProtoFuncToTimeString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsString(formatTime(t, utc));
+}
+
+JSValue* DateProtoFuncToLocaleString::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+#if PLATFORM(MAC)
+    double secs = floor(milli / msPerSecond);
+    return jsString(formatLocaleDate(exec, secs, true, true, args));
+#else
+    const bool utc = false;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return formatLocaleDate(t, LocaleDateAndTime);
+#endif
+}
+
+JSValue* DateProtoFuncToLocaleDateString::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+#if PLATFORM(MAC)
+    double secs = floor(milli / msPerSecond);
+    return jsString(formatLocaleDate(exec, secs, true, false, args));
+#else
+    const bool utc = false;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return formatLocaleDate(t, LocaleDate);
+#endif
+}
+
+JSValue* DateProtoFuncToLocaleTimeString::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+#if PLATFORM(MAC)
+    double secs = floor(milli / msPerSecond);
+    return jsString(formatLocaleDate(exec, secs, false, true, args));
+#else
+    const bool utc = false;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return formatLocaleDate(t, LocaleTime);
+#endif
+}
+
+JSValue* DateProtoFuncValueOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    return jsNumber(milli);
+}
+
+JSValue* DateProtoFuncGetTime::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    return jsNumber(milli);
+}
+
+JSValue* DateProtoFuncGetFullYear::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(1900 + t.year);
+}
+
+JSValue* DateProtoFuncGetUTCFullYear::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(1900 + t.year);
+}
+
+JSValue* DateProtoFuncToGMTString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsString("Invalid Date");
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValue* DateProtoFuncGetMonth::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.month);
+}
+
+JSValue* DateProtoFuncGetUTCMonth::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.month);
+}
+
+JSValue* DateProtoFuncGetDate::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.monthDay);
+}
+
+JSValue* DateProtoFuncGetUTCDate::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.monthDay);
+}
+
+JSValue* DateProtoFuncGetDay::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.weekDay);
+}
+
+JSValue* DateProtoFuncGetUTCDay::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.weekDay);
+}
+
+JSValue* DateProtoFuncGetHours::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.hour);
 }
+
+JSValue* DateProtoFuncGetUTCHours::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.hour);
+}
+
+JSValue* DateProtoFuncGetMinutes::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.minute);
+}
+
+JSValue* DateProtoFuncGetUTCMinutes::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.minute);
+}
+
+JSValue* DateProtoFuncGetSeconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.second);
+}
+
+JSValue* DateProtoFuncGetUTCSeconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(t.second);
+}
+
+JSValue* DateProtoFuncGetMilliSeconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+    return jsNumber(ms);
+}
+
+JSValue* DateProtoFuncGetUTCMilliseconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+    return jsNumber(ms);
+}
+
+JSValue* DateProtoFuncGetTimezoneOffset::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+    return jsNumber(-gmtoffset(t) / minutesPerHour);
+}
+
+JSValue* DateProtoFuncSetTime::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+
+    double milli = timeClip(args[0]->toNumber(exec));
+    JSValue* result = jsNumber(milli);
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetMilliSeconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 1, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetUTCMilliseconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 1, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetSeconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 2, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetUTCSeconds::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 2, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetMinutes::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 3, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetUTCMinutes::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 3, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetHours::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 4, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetUTCHours::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingTimeArgs(exec, args, 4, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetDate::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingDateArgs(exec, args, 1, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetUTCDate::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingDateArgs(exec, args, 1, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetMonth::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingDateArgs(exec, args, 2, &ms, &t);    
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetUTCMonth::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingDateArgs(exec, args, 2, &ms, &t);    
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetFullYear::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingDateArgs(exec, args, 3, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetUTCFullYear::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = true;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    fillStructuresUsingDateArgs(exec, args, 3, &ms, &t);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncSetYear::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    double secs = floor(milli / msPerSecond);
+    double ms = milli - secs * msPerSecond;
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    t.year = (args[0]->toInt32(exec) > 99 || args[0]->toInt32(exec) < 0) ? args[0]->toInt32(exec) - 1900 : args[0]->toInt32(exec);
+
+    JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
+    thisDateObj->setInternalValue(result);
+    return result;
+}
+
+JSValue* DateProtoFuncGetYear::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    if (!thisObj->inherits(&DateInstance::info))
+        return throwError(exec, TypeError);
+
+    const bool utc = false;
+
+    DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj); 
+    JSValue* v = thisDateObj->internalValue();
+    double milli = v->toNumber(exec);
+    if (isnan(milli))
+        return jsNaN();
+
+    GregorianDateTime t;
+    msToGregorianDateTime(milli, utc, t);
+
+    // IE returns the full year even in getYear.
+    if (exec->dynamicInterpreter()->compatMode() == Interpreter::IECompat)
+        return jsNumber(1900 + t.year);
+    return jsNumber(t.year);
+}
+
+} // namespace KJS
index 3880c38cebd6d710a53e4a12ce8c4a6939aae932..6c38e921b51b54ded85e235d53b18d53e14b1773 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "function.h"
 #include "JSWrapperObject.h"
+#include "lookup.h"
 
 namespace KJS {
 
@@ -64,24 +65,59 @@ namespace KJS {
      * Class to implement all methods that are properties of the
      * Date.prototype object
      */
-    class DateProtoFunc : public InternalFunctionImp {
-    public:
-        DateProtoFunc(ExecState *, int i, int len, const Identifier& date);
+    
+    // Non-normative properties (Appendix B)
+    // GetYear, SetYear, ToGMTString
 
-        virtual JSValue *callAsFunction(ExecState *, JSObject *thisObj, const List &args);
+#define FOR_EACH_CLASS(macro) \
+    macro(DateProtoFuncToString) \
+    macro(DateProtoFuncToUTCString) \
+    macro(DateProtoFuncToDateString) \
+    macro(DateProtoFuncToTimeString) \
+    macro(DateProtoFuncToLocaleString) \
+    macro(DateProtoFuncToLocaleDateString) \
+    macro(DateProtoFuncToLocaleTimeString) \
+    macro(DateProtoFuncValueOf) \
+    macro(DateProtoFuncGetTime) \
+    macro(DateProtoFuncGetFullYear) \
+    macro(DateProtoFuncGetUTCFullYear) \
+    macro(DateProtoFuncToGMTString) \
+    macro(DateProtoFuncGetMonth) \
+    macro(DateProtoFuncGetUTCMonth) \
+    macro(DateProtoFuncGetDate) \
+    macro(DateProtoFuncGetUTCDate) \
+    macro(DateProtoFuncGetDay) \
+    macro(DateProtoFuncGetUTCDay) \
+    macro(DateProtoFuncGetHours) \
+    macro(DateProtoFuncGetUTCHours) \
+    macro(DateProtoFuncGetMinutes) \
+    macro(DateProtoFuncGetUTCMinutes) \
+    macro(DateProtoFuncGetSeconds) \
+    macro(DateProtoFuncGetUTCSeconds) \
+    macro(DateProtoFuncGetMilliSeconds) \
+    macro(DateProtoFuncGetUTCMilliseconds) \
+    macro(DateProtoFuncGetTimezoneOffset) \
+    macro(DateProtoFuncSetTime) \
+    macro(DateProtoFuncSetMilliSeconds) \
+    macro(DateProtoFuncSetUTCMilliseconds) \
+    macro(DateProtoFuncSetSeconds) \
+    macro(DateProtoFuncSetUTCSeconds) \
+    macro(DateProtoFuncSetMinutes) \
+    macro(DateProtoFuncSetUTCMinutes) \
+    macro(DateProtoFuncSetHours) \
+    macro(DateProtoFuncSetUTCHours) \
+    macro(DateProtoFuncSetDate) \
+    macro(DateProtoFuncSetUTCDate) \
+    macro(DateProtoFuncSetMonth) \
+    macro(DateProtoFuncSetUTCMonth) \
+    macro(DateProtoFuncSetFullYear) \
+    macro(DateProtoFuncSetUTCFullYear) \
+    macro(DateProtoFuncSetYear) \
+    macro(DateProtoFuncGetYear) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
 
-        enum { ToString, ToDateString, ToTimeString, ToLocaleString,
-            ToLocaleDateString, ToLocaleTimeString, ValueOf, GetTime,
-            GetFullYear, GetMonth, GetDate, GetDay, GetHours, GetMinutes,
-            GetSeconds, GetMilliSeconds, GetTimezoneOffset, SetTime,
-            SetMilliSeconds, SetSeconds, SetMinutes, SetHours, SetDate,
-            SetMonth, SetFullYear, ToUTCString,
-            // non-normative properties (Appendix B)
-            GetYear, SetYear, ToGMTString };
-    private:
-        int id;
-        bool utc;
-    };
 
     /**
      * @internal
index e316087c2ecfe96d34cb9673dd929bf33060e101..95dc5cb2ccc3ecc581d20d0ed9c3af3927818a5c 100644 (file)
@@ -66,7 +66,7 @@ int Lookup::find(const struct HashTable *table, const UChar *c, unsigned int len
 {
   const HashEntry *entry = KJS::findEntry(table, UString::Rep::computeHash(c, len), c, len);
   if (entry)
-    return entry->value;
+    return entry->value.intValue;
   return -1;
 }
 
@@ -74,7 +74,7 @@ int Lookup::find(const struct HashTable* table, const Identifier& s)
 {
   const HashEntry* entry = KJS::findEntry(table, s.ustring().rep()->computedHash(), s.data(), s.size());
   if (entry)
-    return entry->value;
+    return entry->value.intValue;
   return -1;
 }
 
index bfa5850b4e0349a429a62ff0326ed3d80376f8b0..f050cb3b034a57aa0eaf90105dea534bb9f772cf 100644 (file)
@@ -36,15 +36,21 @@ namespace KJS {
    * An entry in a hash table.
    */
   struct HashEntry {
+    typedef InternalFunctionImp* (*ConstructFunctionObject)(ExecState*, int, const Identifier&);
+
     /**
      * s is the key (e.g. a property name)
      */
     const char* s;
 
     /**
-     * value is the result value (usually an enum value)
+     * value is the result value (enum value for properties and a function pointer to a constructor factory for functions)
      */
-    int value;
+    union {
+      intptr_t intValue;
+      ConstructFunctionObject functionValue;
+    } value;
+
     /**
      * attr is a set for flags (e.g. the property flags, see object.h)
      */
@@ -119,7 +125,6 @@ namespace KJS {
    * @internal
    * Helper for getStaticFunctionSlot and getStaticPropertySlot
    */
-  template <class FuncImp>
   inline JSValue* staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
   {
       // Look for cached value in dynamic map of properties (in JSObject)
@@ -129,7 +134,7 @@ namespace KJS {
         return cachedVal;
 
       const HashEntry* entry = slot.staticEntry();
-      JSValue* val = new FuncImp(exec, entry->value, entry->params, propertyName);
+      JSValue* val = entry->value.functionValue(exec, entry->params, propertyName); 
       thisObj->putDirect(propertyName, val, entry->attr);
       return val;
   }
@@ -143,7 +148,7 @@ namespace KJS {
   {
       ThisImp* thisObj = static_cast<ThisImp*>(slot.slotBase());
       const HashEntry* entry = slot.staticEntry();
-      return thisObj->getValueProperty(exec, entry->value);
+      return thisObj->getValueProperty(exec, entry->value.intValue);
   }
 
   /**
@@ -166,7 +171,7 @@ namespace KJS {
    * @param table the static hashtable for this class
    * @param thisObj "this"
    */
-  template <class FuncImp, class ThisImp, class ParentImp>
+  template <class ThisImp, class ParentImp>
   inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, 
                                     ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
   {
@@ -176,7 +181,7 @@ namespace KJS {
       return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
 
     if (entry->attr & Function)
-      slot.setStaticEntry(thisObj, entry, staticFunctionGetter<FuncImp>);
+      slot.setStaticEntry(thisObj, entry, staticFunctionGetter);
     else
       slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
 
@@ -188,7 +193,7 @@ namespace KJS {
    * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
    * a dummy getValueProperty.
    */
-  template <class FuncImp, class ParentImp>
+  template <class ParentImp>
   inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table,
                                     JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
   {
@@ -199,7 +204,7 @@ namespace KJS {
 
     ASSERT(entry->attr & Function);
 
-    slot.setStaticEntry(thisObj, entry, staticFunctionGetter<FuncImp>);
+    slot.setStaticEntry(thisObj, entry, staticFunctionGetter);
     return true;
   }
 
@@ -240,7 +245,7 @@ namespace KJS {
     if (entry->attr & Function) // function: put as override property
       thisObj->JSObject::put(exec, propertyName, value, attr);
     else if (!(entry->attr & ReadOnly))
-      thisObj->putValueProperty(exec, entry->value, value, attr);
+      thisObj->putValueProperty(exec, entry->value.intValue, value, attr);
 
     return true;
   }
@@ -325,7 +330,7 @@ namespace KJS {
     \
     };
 
-#define KJS_IMPLEMENT_PROTOTYPE(ClassName, ClassPrototype, ClassFunction) \
+#define KJS_IMPLEMENT_PROTOTYPE(ClassName, ClassPrototype) \
     const ClassInfo ClassPrototype::info = { ClassName"Prototype", 0, &ClassPrototype##Table  }; \
     JSObject* ClassPrototype::self(ExecState* exec) \
     { \
@@ -334,22 +339,24 @@ namespace KJS {
     } \
     bool ClassPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) \
     { \
-      return getStaticFunctionSlot<ClassFunction, JSObject>(exec, &ClassPrototype##Table, this, propertyName, slot); \
+      return getStaticFunctionSlot<JSObject>(exec, &ClassPrototype##Table, this, propertyName, slot); \
     }
 
-#define KJS_IMPLEMENT_PROTOTYPE_FUNCTION(ClassFunction) \
-  class ClassFunction : public InternalFunctionImp { \
-  public: \
-    ClassFunction(ExecState* exec, int i, int len, const Identifier& name) \
-      : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name) \
-      , id(i) \
-    { \
-       put(exec, exec->propertyNames().length, jsNumber(len), DontDelete|ReadOnly|DontEnum); \
-    } \
-    /* Macro user needs to implement the callAsFunction function. */ \
-    virtual JSValue* callAsFunction(ExecState* exec, JSObject* thisObj, const List& args); \
-  private: \
-    int id; \
-  };
+#define KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE(ClassFunction) \
+    class ClassFunction : public KJS::InternalFunctionImp { \
+    public: \
+        static KJS::InternalFunctionImp* create(KJS::ExecState* exec, int len, const KJS::Identifier& name) \
+        { \
+            return new ClassFunction(exec, len, name); \
+        } \
+        ClassFunction(KJS::ExecState* exec, int len, const KJS::Identifier& name) \
+            : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name) \
+        { \
+            put(exec, exec->propertyNames().length, KJS::jsNumber(len), KJS::DontDelete | KJS::ReadOnly | KJS::DontEnum); \
+        } \
+        \
+        /* Macro user needs to implement the callAsFunction function. */ \
+        virtual KJS::JSValue* callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&); \
+    }; \
 
 #endif // KJS_lookup_h
index a7257cf166499424b3edea0d4cc1a6c8d099602a..f51443d679491832cf8aabeeb110385dae7050b8 100644 (file)
@@ -28,7 +28,7 @@
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
 
-using namespace KJS;
+namespace KJS {
 
 // ------------------------------ MathObjectImp --------------------------------
 
@@ -36,32 +36,32 @@ const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable };
 
 /* Source for math_object.lut.h
 @begin mathTable 21
-  E             MathObjectImp::Euler    DontEnum|DontDelete|ReadOnly
-  LN2           MathObjectImp::Ln2      DontEnum|DontDelete|ReadOnly
-  LN10          MathObjectImp::Ln10     DontEnum|DontDelete|ReadOnly
-  LOG2E         MathObjectImp::Log2E    DontEnum|DontDelete|ReadOnly
-  LOG10E        MathObjectImp::Log10E   DontEnum|DontDelete|ReadOnly
-  PI            MathObjectImp::Pi       DontEnum|DontDelete|ReadOnly
-  SQRT1_2       MathObjectImp::Sqrt1_2  DontEnum|DontDelete|ReadOnly
-  SQRT2         MathObjectImp::Sqrt2    DontEnum|DontDelete|ReadOnly
-  abs           MathObjectImp::Abs      DontEnum|Function 1
-  acos          MathObjectImp::ACos     DontEnum|Function 1
-  asin          MathObjectImp::ASin     DontEnum|Function 1
-  atan          MathObjectImp::ATan     DontEnum|Function 1
-  atan2         MathObjectImp::ATan2    DontEnum|Function 2
-  ceil          MathObjectImp::Ceil     DontEnum|Function 1
-  cos           MathObjectImp::Cos      DontEnum|Function 1
-  exp           MathObjectImp::Exp      DontEnum|Function 1
-  floor         MathObjectImp::Floor    DontEnum|Function 1
-  log           MathObjectImp::Log      DontEnum|Function 1
-  max           MathObjectImp::Max      DontEnum|Function 2
-  min           MathObjectImp::Min      DontEnum|Function 2
-  pow           MathObjectImp::Pow      DontEnum|Function 2
-  random        MathObjectImp::Random   DontEnum|Function 0
-  round         MathObjectImp::Round    DontEnum|Function 1
-  sin           MathObjectImp::Sin      DontEnum|Function 1
-  sqrt          MathObjectImp::Sqrt     DontEnum|Function 1
-  tan           MathObjectImp::Tan      DontEnum|Function 1
+  E             MathObjectImp::Euler           DontEnum|DontDelete|ReadOnly
+  LN2           MathObjectImp::Ln2             DontEnum|DontDelete|ReadOnly
+  LN10          MathObjectImp::Ln10            DontEnum|DontDelete|ReadOnly
+  LOG2E         MathObjectImp::Log2E           DontEnum|DontDelete|ReadOnly
+  LOG10E        MathObjectImp::Log10E          DontEnum|DontDelete|ReadOnly
+  PI            MathObjectImp::Pi              DontEnum|DontDelete|ReadOnly
+  SQRT1_2       MathObjectImp::Sqrt1_2         DontEnum|DontDelete|ReadOnly
+  SQRT2         MathObjectImp::Sqrt2           DontEnum|DontDelete|ReadOnly
+  abs           &MathProtoFuncAbs::create      DontEnum|Function 1
+  acos          &MathProtoFuncACos::create     DontEnum|Function 1
+  asin          &MathProtoFuncASin::create     DontEnum|Function 1
+  atan          &MathProtoFuncATan::create     DontEnum|Function 1
+  atan2         &MathProtoFuncATan2::create    DontEnum|Function 2
+  ceil          &MathProtoFuncCeil::create     DontEnum|Function 1
+  cos           &MathProtoFuncCos::create      DontEnum|Function 1
+  exp           &MathProtoFuncExp::create      DontEnum|Function 1
+  floor         &MathProtoFuncFloor::create    DontEnum|Function 1
+  log           &MathProtoFuncLog::create      DontEnum|Function 1
+  max           &MathProtoFuncMax::create      DontEnum|Function 2
+  min           &MathProtoFuncMin::create      DontEnum|Function 2
+  pow           &MathProtoFuncPow::create      DontEnum|Function 2
+  random        &MathProtoFuncRandom::create   DontEnum|Function 0 
+  round         &MathProtoFuncRound::create    DontEnum|Function 1
+  sin           &MathProtoFuncSin::create      DontEnum|Function 1
+  sqrt          &MathProtoFuncSqrt::create     DontEnum|Function 1
+  tan           &MathProtoFuncTan::create      DontEnum|Function 1
 @end
 */
 
@@ -75,7 +75,7 @@ MathObjectImp::MathObjectImp(ExecState * /*exec*/,
 
 bool MathObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
 {
-  return getStaticPropertySlot<MathFuncImp, MathObjectImp, JSObject>(exec, &mathTable, this, propertyName, slot);
+  return getStaticPropertySlot<MathObjectImp, JSObject>(exec, &mathTable, this, propertyName, slot);
 }
 
 JSValue *MathObjectImp::getValueProperty(ExecState *, int token) const
@@ -113,126 +113,154 @@ JSValue *MathObjectImp::getValueProperty(ExecState *, int token) const
   return jsNumber(d);
 }
 
-// ------------------------------ MathObjectImp --------------------------------
+// ------------------------------ Functions --------------------------------
 
-static bool didInitRandom;
+JSValue* MathProtoFuncAbs::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return signbit(arg) ? jsNumber(-arg) : jsNumber(arg);
+}
 
-MathFuncImp::MathFuncImp(ExecState* exec, int i, int l, const Identifier& name)
-  : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
-  , id(i)
+JSValue* MathProtoFuncACos::callAsFunction(ExecState* exec, JSObject*, const List& args)
 {
-  putDirect(exec->propertyNames().length, l, DontDelete|ReadOnly|DontEnum);
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(acos(arg));
 }
 
-JSValue *MathFuncImp::callAsFunction(ExecState *exec, JSObject* /*thisObj*/, const List &args)
+JSValue* MathProtoFuncASin::callAsFunction(ExecState* exec, JSObject*, const List& args)
 {
-  double arg = args[0]->toNumber(exec);
-  double arg2 = args[1]->toNumber(exec);
-  double result;
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(asin(arg));
+}
 
-  switch (id) {
-  case MathObjectImp::Abs:
-    result = signbit(arg) ? -arg : arg;
-    break;
-  case MathObjectImp::ACos:
-    result = acos(arg);
-    break;
-  case MathObjectImp::ASin:
-    result = asin(arg);
-    break;
-  case MathObjectImp::ATan:
-    result = atan(arg);
-    break;
-  case MathObjectImp::ATan2:
-    result = atan2(arg, arg2);
-    break;
-  case MathObjectImp::Ceil:
+JSValue* MathProtoFuncATan::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(atan(arg));
+}
+
+JSValue* MathProtoFuncATan2::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    double arg2 = args[1]->toNumber(exec);
+    return jsNumber(atan2(arg, arg2));
+}
+
+JSValue* MathProtoFuncCeil::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
     if (signbit(arg) && arg > -1.0)
-      result = -0.0;
-    else
-      result = ceil(arg);
-    break;
-  case MathObjectImp::Cos:
-    result = cos(arg);
-    break;
-  case MathObjectImp::Exp:
-    result = exp(arg);
-    break;
-  case MathObjectImp::Floor:
+        return jsNumber(-0.0);
+    return jsNumber(ceil(arg));
+}
+
+JSValue* MathProtoFuncCos::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(cos(arg));
+}
+
+JSValue* MathProtoFuncExp::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(exp(arg));
+}
+
+JSValue* MathProtoFuncFloor::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
     if (signbit(arg) && arg == 0.0)
-      result = -0.0;
-    else
-      result = floor(arg);
-    break;
-  case MathObjectImp::Log:
-    result = log(arg);
-    break;
-  case MathObjectImp::Max: {
-    unsigned int argsCount = args.size();
-    result = -Inf;
-    for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
-      double val = args[k]->toNumber(exec);
-      if ( isnan( val ) )
-      {
-        result = NaN;
-        break;
-      }
-      if ( val > result || (val == 0 && result == 0 && !signbit(val)) )
-        result = val;
+        return jsNumber(-0.0);
+    return jsNumber(floor(arg));
+}
+
+JSValue* MathProtoFuncLog::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(log(arg));
+}
+
+JSValue* MathProtoFuncMax::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    unsigned argsCount = args.size();
+    double result = -Inf;
+    for (unsigned k = 0; k < argsCount; ++k) {
+        double val = args[k]->toNumber(exec);
+        if (isnan(val)) {
+            result = NaN;
+            break;
+        }
+        if (val > result || (val == 0 && result == 0 && !signbit(val)))
+            result = val;
     }
-    break;
-  }
-  case MathObjectImp::Min: {
-    unsigned int argsCount = args.size();
-    result = +Inf;
-    for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
-      double val = args[k]->toNumber(exec);
-      if ( isnan( val ) )
-      {
-        result = NaN;
-        break;
-      }
-      if ( val < result || (val == 0 && result == 0 && signbit(val)) )
-        result = val;
+    return jsNumber(result);
+}
+
+JSValue* MathProtoFuncMin::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    unsigned argsCount = args.size();
+    double result = +Inf;
+    for (unsigned k = 0; k < argsCount; ++k) {
+        double val = args[k]->toNumber(exec);
+        if (isnan(val)) {
+            result = NaN;
+            break;
+        }
+        if (val < result || (val == 0 && result == 0 && signbit(val)))
+            result = val;
     }
-    break;
-  }
-  case MathObjectImp::Pow:
+    return jsNumber(result);
+}
+
+JSValue* MathProtoFuncPow::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
     // ECMA 15.8.2.1.13
+
+    double arg = args[0]->toNumber(exec);
+    double arg2 = args[1]->toNumber(exec);
+
     if (isnan(arg2))
-      result = NaN;
-    else if (isinf(arg2) && fabs(arg) == 1)
-      result = NaN;
-    else
-      result = pow(arg, arg2);
-    break;
-  case MathObjectImp::Random:
-      if (!didInitRandom) {
-          wtf_random_init();
-          didInitRandom = true;
-      }
-      result = wtf_random();
-      break;
-  case MathObjectImp::Round:
+        return jsNumber(NaN);
+    if (isinf(arg2) && fabs(arg) == 1)
+        return jsNumber(NaN);
+    return jsNumber(pow(arg, arg2));
+}
+
+static bool didInitRandom;
+
+JSValue* MathProtoFuncRandom::callAsFunction(ExecState*, JSObject*, const List&)
+{
+    if (!didInitRandom) {
+        wtf_random_init();
+        didInitRandom = true;
+    }
+    return jsNumber(wtf_random());
+}
+
+JSValue* MathProtoFuncRound::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
     if (signbit(arg) && arg >= -0.5)
-        result = -0.0;
-    else
-        result = floor(arg + 0.5);
-    break;
-  case MathObjectImp::Sin:
-    result = sin(arg);
-    break;
-  case MathObjectImp::Sqrt:
-    result = sqrt(arg);
-    break;
-  case MathObjectImp::Tan:
-    result = tan(arg);
-    break;
+         return jsNumber(-0.0);
+    return jsNumber(floor(arg + 0.5));
+}
 
-  default:
-    result = 0.0;
-    ASSERT(0);
-  }
+JSValue* MathProtoFuncSin::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(sin(arg));
+}
 
-  return jsNumber(result);
+JSValue* MathProtoFuncSqrt::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(sqrt(arg));
 }
+
+JSValue* MathProtoFuncTan::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+    double arg = args[0]->toNumber(exec);
+    return jsNumber(tan(arg));
+}
+
+} // namespace KJS
index 5843e3120d6e2f4daf30a905ffabd796f212ec49..13f94d4fd8498960faacecdc4667e927b795c480 100644 (file)
 #define MATH_OBJECT_H_
 
 #include "function_object.h"
+#include "lookup.h"
 
 namespace KJS {
 
   class MathObjectImp : public JSObject {
   public:
-    MathObjectImp(ExecState *exec,
-                  ObjectPrototype *objProto);
-    bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
-    JSValue *getValueProperty(ExecState *exec, int token) const;
-    virtual const ClassInfo *classInfo() const { return &info; }
+    MathObjectImp(ExecState*, ObjectPrototype*);
+
+    bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+    JSValue* getValueProperty(ExecState*, int token) const;
+
+    virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
-    enum { Euler, Ln2, Ln10, Log2E, Log10E, Pi, Sqrt1_2, Sqrt2,
-           Abs, ACos, ASin, ATan, ATan2, Ceil, Cos, Pow,
-           Exp, Floor, Log, Max, Min, Random, Round, Sin, Sqrt, Tan };
-  };
 
-  class MathFuncImp : public InternalFunctionImp {
-  public:
-    MathFuncImp(ExecState *exec, int i, int l, const Identifier&);
-    virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-  private:
-    int id;
+    enum { Euler, Ln2, Ln10, Log2E, Log10E, Pi, Sqrt1_2, Sqrt2 };
   };
 
-} // namespace
 
-#endif
+#define FOR_EACH_CLASS(macro) \
+    macro(MathProtoFuncAbs) \
+    macro(MathProtoFuncACos) \
+    macro(MathProtoFuncASin) \
+    macro(MathProtoFuncATan) \
+    macro(MathProtoFuncATan2) \
+    macro(MathProtoFuncCeil) \
+    macro(MathProtoFuncCos) \
+    macro(MathProtoFuncExp) \
+    macro(MathProtoFuncFloor) \
+    macro(MathProtoFuncLog) \
+    macro(MathProtoFuncMax) \
+    macro(MathProtoFuncMin) \
+    macro(MathProtoFuncPow) \
+    macro(MathProtoFuncRandom) \
+    macro(MathProtoFuncRound) \
+    macro(MathProtoFuncSin) \
+    macro(MathProtoFuncSqrt) \
+    macro(MathProtoFuncTan) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
+
+} // namespace KJS
+
+#endif // MATH_OBJECT_H_
index e59694e2b2163e7e49a0bd030f66fc86a4bca13e..3e8dc7b22ba924a3fb6e1ce9ac66024a9eae1e81 100644 (file)
@@ -129,42 +129,42 @@ void StringInstance::getPropertyNames(ExecState* exec, PropertyNameArray& proper
 const ClassInfo StringPrototype::info = { "String", &StringInstance::info, &stringTable };
 /* Source for string_object.lut.h
 @begin stringTable 26
-  toString              StringProtoFunc::ToString       DontEnum|Function       0
-  valueOf               StringProtoFunc::ValueOf        DontEnum|Function       0
-  charAt                StringProtoFunc::CharAt         DontEnum|Function       1
-  charCodeAt            StringProtoFunc::CharCodeAt     DontEnum|Function       1
-  concat                StringProtoFunc::Concat         DontEnum|Function       1
-  indexOf               StringProtoFunc::IndexOf        DontEnum|Function       1
-  lastIndexOf           StringProtoFunc::LastIndexOf    DontEnum|Function       1
-  match                 StringProtoFunc::Match          DontEnum|Function       1
-  replace               StringProtoFunc::Replace        DontEnum|Function       2
-  search                StringProtoFunc::Search         DontEnum|Function       1
-  slice                 StringProtoFunc::Slice          DontEnum|Function       2
-  split                 StringProtoFunc::Split          DontEnum|Function       2
-  substr                StringProtoFunc::Substr         DontEnum|Function       2
-  substring             StringProtoFunc::Substring      DontEnum|Function       2
-  toLowerCase           StringProtoFunc::ToLowerCase    DontEnum|Function       0
-  toUpperCase           StringProtoFunc::ToUpperCase    DontEnum|Function       0
-  toLocaleLowerCase     StringProtoFunc::ToLocaleLowerCase DontEnum|Function    0
-  toLocaleUpperCase     StringProtoFunc::ToLocaleUpperCase DontEnum|Function    0
-  localeCompare         StringProtoFunc::LocaleCompare  DontEnum|Function       1
+  toString              &StringProtoFuncToString::create          DontEnum|Function       0
+  valueOf               &StringProtoFuncValueOf::create           DontEnum|Function       0
+  charAt                &StringProtoFuncCharAt::create            DontEnum|Function       1
+  charCodeAt            &StringProtoFuncCharCodeAt::create        DontEnum|Function       1
+  concat                &StringProtoFuncConcat::create            DontEnum|Function       1
+  indexOf               &StringProtoFuncIndexOf::create           DontEnum|Function       1
+  lastIndexOf           &StringProtoFuncLastIndexOf::create       DontEnum|Function       1
+  match                 &StringProtoFuncMatch::create             DontEnum|Function       1
+  replace               &StringProtoFuncReplace::create           DontEnum|Function       2
+  search                &StringProtoFuncSearch::create            DontEnum|Function       1
+  slice                 &StringProtoFuncSlice::create             DontEnum|Function       2
+  split                 &StringProtoFuncSplit::create             DontEnum|Function       2
+  substr                &StringProtoFuncSubstr::create            DontEnum|Function       2
+  substring             &StringProtoFuncSubstring::create         DontEnum|Function       2
+  toLowerCase           &StringProtoFuncToLowerCase::create       DontEnum|Function       0
+  toUpperCase           &StringProtoFuncToUpperCase::create       DontEnum|Function       0
+  toLocaleLowerCase     &StringProtoFuncToLocaleLowerCase::create DontEnum|Function       0
+  toLocaleUpperCase     &StringProtoFuncToLocaleUpperCase::create DontEnum|Function       0
+  localeCompare         &StringProtoFuncLocaleCompare::create     DontEnum|Function       1
 #
 # Under here: html extension, should only exist if KJS_PURE_ECMA is not defined
 # I guess we need to generate two hashtables in the .lut.h file, and use #ifdef
 # to select the right one... TODO. #####
-  big                   StringProtoFunc::Big            DontEnum|Function       0
-  small                 StringProtoFunc::Small          DontEnum|Function       0
-  blink                 StringProtoFunc::Blink          DontEnum|Function       0
-  bold                  StringProtoFunc::Bold           DontEnum|Function       0
-  fixed                 StringProtoFunc::Fixed          DontEnum|Function       0
-  italics               StringProtoFunc::Italics        DontEnum|Function       0
-  strike                StringProtoFunc::Strike         DontEnum|Function       0
-  sub                   StringProtoFunc::Sub            DontEnum|Function       0
-  sup                   StringProtoFunc::Sup            DontEnum|Function       0
-  fontcolor             StringProtoFunc::Fontcolor      DontEnum|Function       1
-  fontsize              StringProtoFunc::Fontsize       DontEnum|Function       1
-  anchor                StringProtoFunc::Anchor         DontEnum|Function       1
-  link                  StringProtoFunc::Link           DontEnum|Function       1
+  big                   &StringProtoFuncBig::create               DontEnum|Function       0
+  small                 &StringProtoFuncSmall::create             DontEnum|Function       0
+  blink                 &StringProtoFuncBlink::create             DontEnum|Function       0
+  bold                  &StringProtoFuncBold::create              DontEnum|Function       0
+  fixed                 &StringProtoFuncFixed::create             DontEnum|Function       0
+  italics               &StringProtoFuncItalics::create           DontEnum|Function       0
+  strike                &StringProtoFuncStrike::create            DontEnum|Function       0
+  sub                   &StringProtoFuncSub::create               DontEnum|Function       0
+  sup                   &StringProtoFuncSup::create               DontEnum|Function       0
+  fontcolor             &StringProtoFuncFontcolor::create         DontEnum|Function       1
+  fontsize              &StringProtoFuncFontsize::create          DontEnum|Function       1
+  anchor                &StringProtoFuncAnchor::create            DontEnum|Function       1
+  link                  &StringProtoFuncLink::create              DontEnum|Function       1
 @end
 */
 // ECMA 15.5.4
@@ -177,17 +177,10 @@ StringPrototype::StringPrototype(ExecState* exec, ObjectPrototype* objProto)
 
 bool StringPrototype::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
 {
-  return getStaticFunctionSlot<StringProtoFunc, StringInstance>(exec, &stringTable, this, propertyName, slot);
+  return getStaticFunctionSlot<StringInstance>(exec, &stringTable, this, propertyName, slot);
 }
 
-// ------------------------------ StringProtoFunc ---------------------------
-
-StringProtoFunc::StringProtoFunc(ExecState* exec, int i, int len, const Identifier& name)
-  : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
-  , id(i)
-{
-  putDirect(exec->propertyNames().length, len, DontDelete | ReadOnly | DontEnum);
-}
+// ------------------------------ Functions --------------------------
 
 static inline void expandSourceRanges(UString::Range * & array, int& count, int& capacity)
 {
@@ -434,83 +427,113 @@ static JSValue *replace(ExecState *exec, StringImp* sourceVal, JSValue *pattern,
   return jsString(source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen));
 }
 
-// ECMA 15.5.4.2 - 15.5.4.20
-JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+JSValue* StringProtoFuncToString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
 {
-  JSValue* result = NULL;
+    if (!thisObj->inherits(&StringInstance::info))
+        return throwError(exec, TypeError);
+
+    return static_cast<StringInstance*>(thisObj)->internalValue();
+}
 
-  // toString and valueOf are no generic function.
-  if (id == ToString || id == ValueOf) {
+JSValue* StringProtoFuncValueOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
     if (!thisObj->inherits(&StringInstance::info))
-      return throwError(exec, TypeError);
+        return throwError(exec, TypeError);
 
     return static_cast<StringInstance*>(thisObj)->internalValue();
-  }
+}
 
-  UString u, u2, u3;
-  int pos, p0, i;
-  double dpos;
-  double d = 0.0;
-
-  // This optimizes the common case that thisObj is a StringInstance
-  UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
-  int len = s.size();
-  JSValue *a0 = args[0];
-  JSValue *a1 = args[1];
-
-  switch (id) {
-  case ToString:
-  case ValueOf:
-    // handled above
-    break;
-  case CharAt:
-    dpos = a0->toInteger(exec);
+JSValue* StringProtoFuncCharAt::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    int len = s.size();
+
+    UString u;
+    JSValue* a0 = args[0];
+    double dpos = a0->toInteger(exec);
     if (dpos >= 0 && dpos < len)
       u = s.substr(static_cast<int>(dpos), 1);
     else
       u = "";
-    result = jsString(u);
-    break;
-  case CharCodeAt:
-    dpos = a0->toInteger(exec);
+    return jsString(u);
+}
+
+JSValue* StringProtoFuncCharCodeAt::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    int len = s.size();
+
+    JSValue* result = 0;
+
+    JSValue* a0 = args[0];
+    double dpos = a0->toInteger(exec);
     if (dpos >= 0 && dpos < len)
       result = jsNumber(s[static_cast<int>(dpos)].unicode());
     else
       result = jsNaN();
-    break;
-  case Concat: {
+    return result;
+}
+
+JSValue* StringProtoFuncConcat::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+
     List::const_iterator end = args.end();
     for (List::const_iterator it = args.begin(); it != end; ++it) {
         s += (*it)->toString(exec);
     }
-    result = jsString(s);
-    break;
-  }
-  case IndexOf:
-    u2 = a0->toString(exec);
-    dpos = a1->toInteger(exec);
+    return jsString(s);
+}
+
+JSValue* StringProtoFuncIndexOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    int len = s.size();
+
+    JSValue* a0 = args[0];
+    JSValue* a1 = args[1];
+    UString u2 = a0->toString(exec);
+    double dpos = a1->toInteger(exec);
     if (dpos < 0)
-      dpos = 0;
+        dpos = 0;
     else if (dpos > len)
-      dpos = len;
-    result = jsNumber(s.find(u2, static_cast<int>(dpos)));
-    break;
-  case LastIndexOf:
-    u2 = a0->toString(exec);
-    d = a1->toNumber(exec);
-    dpos = a1->toIntegerPreserveNaN(exec);
+        dpos = len;
+    return jsNumber(s.find(u2, static_cast<int>(dpos)));
+}
+
+JSValue* StringProtoFuncLastIndexOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    int len = s.size();
+
+    JSValue* a0 = args[0];
+    JSValue* a1 = args[1];
+    
+    UString u2 = a0->toString(exec);
+    double dpos = a1->toIntegerPreserveNaN(exec);
     if (dpos < 0)
-      dpos = 0;
+        dpos = 0;
     else if (!(dpos <= len)) // true for NaN
-      dpos = len;
-    result = jsNumber(s.rfind(u2, static_cast<int>(dpos)));
-    break;
-  case Match:
-  case Search: {
-    u = s;
-    RegExp *reg, *tmpReg = 0;
-    RegExpImp *imp = 0;
+        dpos = len;
+    return jsNumber(s.rfind(u2, static_cast<int>(dpos)));
+}
+
+JSValue* StringProtoFuncMatch::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+
+    JSValue* a0 = args[0];
+
+    UString u = s;
+    RegExp* reg;
+    RegExp* tmpReg = 0;
+    RegExpImp* imp = 0;
     if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpImp::info)) {
       reg = static_cast<RegExpImp *>(a0)->regExp();
     } else { 
@@ -525,80 +548,128 @@ JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, con
     int pos;
     int matchLength;
     regExpObj->performMatch(reg, u, 0, pos, matchLength);
-    if (id == Search) {
-      result = jsNumber(pos);
+    JSValue* result;
+    if (!(reg->global())) {
+      // case without 'g' flag is handled like RegExp.prototype.exec
+      if (pos < 0)
+        result = jsNull();
+      else
+        result = regExpObj->arrayOfMatches(exec);
     } else {
-      // Match
-      if (!(reg->global())) {
-        // case without 'g' flag is handled like RegExp.prototype.exec
-        if (pos < 0)
-          result = jsNull();
-        else
-          result = regExpObj->arrayOfMatches(exec);
+      // return array of matches
+      List list;
+      int lastIndex = 0;
+      while (pos >= 0) {
+        list.append(jsString(u.substr(pos, matchLength)));
+        lastIndex = pos;
+        pos += matchLength == 0 ? 1 : matchLength;
+        regExpObj->performMatch(reg, u, pos, pos, matchLength);
+      }
+      if (imp)
+        imp->put(exec, exec->propertyNames().lastIndex, jsNumber(lastIndex), DontDelete|DontEnum);
+      if (list.isEmpty()) {
+        // if there are no matches at all, it's important to return
+        // Null instead of an empty array, because this matches
+        // other browsers and because Null is a false value.
+        result = jsNull();
       } else {
-        // return array of matches
-        List list;
-        int lastIndex = 0;
-        while (pos >= 0) {
-          list.append(jsString(u.substr(pos, matchLength)));
-          lastIndex = pos;
-          pos += matchLength == 0 ? 1 : matchLength;
-          regExpObj->performMatch(reg, u, pos, pos, matchLength);
-        }
-        if (imp)
-          imp->put(exec, exec->propertyNames().lastIndex, jsNumber(lastIndex), DontDelete|DontEnum);
-        if (list.isEmpty()) {
-          // if there are no matches at all, it's important to return
-          // Null instead of an empty array, because this matches
-          // other browsers and because Null is a false value.
-          result = jsNull();
-        } else {
-          result = exec->lexicalInterpreter()->builtinArray()->construct(exec, list);
-        }
+        result = exec->lexicalInterpreter()->builtinArray()->construct(exec, list);
       }
     }
     delete tmpReg;
-    break;
-  }
-  case Replace: {
+    return result;
+}
+
+JSValue* StringProtoFuncSearch::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+
+    JSValue* a0 = args[0];
+
+    UString u = s;
+    RegExp* reg;
+    RegExp* tmpReg = 0;
+    if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpImp::info)) {
+      reg = static_cast<RegExpImp *>(a0)->regExp();
+    } else { 
+      /*
+       *  ECMA 15.5.4.12 String.prototype.search (regexp)
+       *  If regexp is not an object whose [[Class]] property is "RegExp", it is
+       *  replaced with the result of the expression new RegExp(regexp).
+       */
+      reg = tmpReg = new RegExp(a0->toString(exec));
+    }
+    RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp());
+    int pos;
+    int matchLength;
+    regExpObj->performMatch(reg, u, 0, pos, matchLength);
+    delete tmpReg;
+    return jsNumber(pos);
+}
+
+JSValue* StringProtoFuncReplace::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+
     StringImp* sVal = thisObj->inherits(&StringInstance::info) ?
       static_cast<StringInstance*>(thisObj)->internalValue() :
       static_cast<StringImp*>(jsString(s));
 
-    result = replace(exec, sVal, a0, a1);
-    break;
-  }
-  case Slice:
-    {
-      // The arg processing is very much like ArrayProtoFunc::Slice
-      double start = a0->toInteger(exec);
-      double end = a1->isUndefined() ? len : a1->toInteger(exec);
-      double from = start < 0 ? len + start : start;
-      double to = end < 0 ? len + end : end;
-      if (to > from && to > 0 && from < len) {
+    JSValue* a0 = args[0];
+    JSValue* a1 = args[1];
+
+    return replace(exec, sVal, a0, a1);
+}
+
+JSValue* StringProtoFuncSlice::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    int len = s.size();
+
+    JSValue* a0 = args[0];
+    JSValue* a1 = args[1];
+
+    // The arg processing is very much like ArrayProtoFunc::Slice
+    double start = a0->toInteger(exec);
+    double end = a1->isUndefined() ? len : a1->toInteger(exec);
+    double from = start < 0 ? len + start : start;
+    double to = end < 0 ? len + end : end;
+    if (to > from && to > 0 && from < len) {
         if (from < 0)
-          from = 0;
+            from = 0;
         if (to > len)
-          to = len;
-        result = jsString(s.substr(static_cast<int>(from), static_cast<int>(to - from)));
-      } else {
-        result = jsString("");
-      }
-      break;
+            to = len;
+        return jsString(s.substr(static_cast<int>(from), static_cast<int>(to - from)));
     }
-    case Split: {
+
+    return jsString("");
+}
+
+JSValue* StringProtoFuncSplit::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+
+    JSValue* a0 = args[0];
+    JSValue* a1 = args[1];
+
     JSObject *constructor = exec->lexicalInterpreter()->builtinArray();
     JSObject *res = static_cast<JSObject *>(constructor->construct(exec,List::empty()));
-    result = res;
-    u = s;
-    i = p0 = 0;
+    JSValue* result = res;
+    UString u = s;
+    int pos;
+    int i = 0;
+    int p0 = 0;
     uint32_t limit = a1->isUndefined() ? 0xFFFFFFFFU : a1->toUInt32(exec);
     if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpImp::info)) {
       RegExp *reg = static_cast<RegExpImp *>(a0)->regExp();
       if (u.isEmpty() && reg->match(u, 0) >= 0) {
         // empty string matched by regexp -> empty array
         res->put(exec, exec->propertyNames().length, jsNumber(0));
-        break;
+        return result;
       }
       pos = 0;
       while (static_cast<uint32_t>(i) != limit && pos < u.size()) {
@@ -622,12 +693,12 @@ JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, con
         }
       }
     } else {
-      u2 = a0->toString(exec);
+      UString u2 = a0->toString(exec);
       if (u2.isEmpty()) {
         if (u.isEmpty()) {
           // empty separator matches empty string -> empty array
           put(exec, exec->propertyNames().length, jsNumber(0));
-          break;
+          return result;
         } else {
           while (static_cast<uint32_t>(i) != limit && i < u.size()-1)
             res->put(exec, i++, jsString(u.substr(p0++, 1)));
@@ -644,9 +715,20 @@ JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, con
     if (static_cast<uint32_t>(i) != limit)
       res->put(exec, i++, jsString(u.substr(p0)));
     res->put(exec, exec->propertyNames().length, jsNumber(i));
-    }
-    break;
-  case Substr: {
+    return result;
+}
+
+JSValue* StringProtoFuncSubstr::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    int len = s.size();
+
+    JSValue* a0 = args[0];
+    JSValue* a1 = args[1];
+
+    double d = 0.0;
+
     double start = a0->toInteger(exec);
     double length = a1->isUndefined() ? len : a1->toInteger(exec);
     if (start >= len)
@@ -660,10 +742,18 @@ JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, con
     }
     if (length > len - d)
       length = len - d;
-    result = jsString(s.substr(static_cast<int>(start), static_cast<int>(length)));
-    break;
-  }
-  case Substring: {
+    return jsString(s.substr(static_cast<int>(start), static_cast<int>(length)));
+}
+
+JSValue* StringProtoFuncSubstring::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    int len = s.size();
+
+    JSValue* a0 = args[0];
+    JSValue* a1 = args[1];
+
     double start = a0->toNumber(exec);
     double end = a1->toNumber(exec);
     if (isnan(start))
@@ -685,11 +775,65 @@ JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, con
       end = start;
       start = temp;
     }
-    result = jsString(s.substr((int)start, (int)end-(int)start));
+    return jsString(s.substr((int)start, (int)end-(int)start));
+}
+
+JSValue* StringProtoFuncToLowerCase::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    
+    StringImp* sVal = thisObj->inherits(&StringInstance::info)
+        ? static_cast<StringInstance*>(thisObj)->internalValue()
+        : static_cast<StringImp*>(jsString(s));
+    int ssize = s.size();
+    if (!ssize)
+        return sVal;
+    Vector< ::UChar> buffer(ssize);
+    bool error;
+    int length = Unicode::toLower(buffer.data(), ssize, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
+    if (error) {
+        buffer.resize(length);
+        length = Unicode::toLower(buffer.data(), length, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
+        if (error)
+            return sVal;
     }
-    break;
-  case ToLowerCase:
-  case ToLocaleLowerCase: { // FIXME: See http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt for locale-sensitive mappings that aren't implemented.
+    if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
+        return sVal;
+    return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
+}
+
+JSValue* StringProtoFuncToUpperCase::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+
+    StringImp* sVal = thisObj->inherits(&StringInstance::info)
+        ? static_cast<StringInstance*>(thisObj)->internalValue()
+        : static_cast<StringImp*>(jsString(s));
+    int ssize = s.size();
+    if (!ssize)
+        return sVal;
+    Vector< ::UChar> buffer(ssize);
+    bool error;
+    int length = Unicode::toUpper(buffer.data(), ssize, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
+    if (error) {
+        buffer.resize(length);
+        length = Unicode::toUpper(buffer.data(), length, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
+        if (error)
+            return sVal;
+    }
+    if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
+        return sVal;
+    return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
+}
+
+JSValue* StringProtoFuncToLocaleLowerCase::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    
+    // FIXME: See http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt for locale-sensitive mappings that aren't implemented.
     StringImp* sVal = thisObj->inherits(&StringInstance::info)
         ? static_cast<StringInstance*>(thisObj)->internalValue()
         : static_cast<StringImp*>(jsString(s));
@@ -708,9 +852,13 @@ JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, con
     if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
         return sVal;
     return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
-  }
-  case ToUpperCase:
-  case ToLocaleUpperCase: { // FIXME: See http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt for locale-sensitive mappings that aren't implemented.
+}
+
+JSValue* StringProtoFuncToLocaleUpperCase::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+
     StringImp* sVal = thisObj->inherits(&StringInstance::info)
         ? static_cast<StringInstance*>(thisObj)->internalValue()
         : static_cast<StringImp*>(jsString(s));
@@ -729,57 +877,118 @@ JSValue* StringProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, con
     if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
         return sVal;
     return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
-  }
-  case LocaleCompare:
+}
+
+JSValue* StringProtoFuncLocaleCompare::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
     if (args.size() < 1)
       return jsNumber(0);
+
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    JSValue* a0 = args[0];
     return jsNumber(localeCompare(s, a0->toString(exec)));
+}
+
 #ifndef KJS_PURE_ECMA
-  case Big:
-    result = jsString("<big>" + s + "</big>");
-    break;
-  case Small:
-    result = jsString("<small>" + s + "</small>");
-    break;
-  case Blink:
-    result = jsString("<blink>" + s + "</blink>");
-    break;
-  case Bold:
-    result = jsString("<b>" + s + "</b>");
-    break;
-  case Fixed:
-    result = jsString("<tt>" + s + "</tt>");
-    break;
-  case Italics:
-    result = jsString("<i>" + s + "</i>");
-    break;
-  case Strike:
-    result = jsString("<strike>" + s + "</strike>");
-    break;
-  case Sub:
-    result = jsString("<sub>" + s + "</sub>");
-    break;
-  case Sup:
-    result = jsString("<sup>" + s + "</sup>");
-    break;
-  case Fontcolor:
-    result = jsString("<font color=\"" + a0->toString(exec) + "\">" + s + "</font>");
-    break;
-  case Fontsize:
-    result = jsString("<font size=\"" + a0->toString(exec) + "\">" + s + "</font>");
-    break;
-  case Anchor:
-    result = jsString("<a name=\"" + a0->toString(exec) + "\">" + s + "</a>");
-    break;
-  case Link:
-    result = jsString("<a href=\"" + a0->toString(exec) + "\">" + s + "</a>");
-    break;
-#endif
-  }
 
-  return result;
+JSValue* StringProtoFuncBig::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<big>" + s + "</big>");
 }
 
+JSValue* StringProtoFuncSmall::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<small>" + s + "</small>");
+}
+
+JSValue* StringProtoFuncBlink::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<blink>" + s + "</blink>");
+}
+
+JSValue* StringProtoFuncBold::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<b>" + s + "</b>");
+}
+
+JSValue* StringProtoFuncFixed::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<tt>" + s + "</tt>");
+}
+
+JSValue* StringProtoFuncItalics::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<i>" + s + "</i>");
+}
+
+JSValue* StringProtoFuncStrike::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<strike>" + s + "</strike>");
+}
+
+JSValue* StringProtoFuncSub::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<sub>" + s + "</sub>");
+}
+
+JSValue* StringProtoFuncSup::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    return jsString("<sup>" + s + "</sup>");
+}
+
+JSValue* StringProtoFuncFontcolor::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    JSValue* a0 = args[0];
+    return jsString("<font color=\"" + a0->toString(exec) + "\">" + s + "</font>");
+}
+
+JSValue* StringProtoFuncFontsize::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    JSValue* a0 = args[0];
+    return jsString("<font size=\"" + a0->toString(exec) + "\">" + s + "</font>");
+}
+
+JSValue* StringProtoFuncAnchor::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    JSValue* a0 = args[0];
+    return jsString("<a name=\"" + a0->toString(exec) + "\">" + s + "</a>");
+}
+
+JSValue* StringProtoFuncLink::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // This optimizes the common case that thisObj is a StringInstance
+    UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
+    JSValue* a0 = args[0];
+    return jsString("<a href=\"" + a0->toString(exec) + "\">" + s + "</a>");
+}
+
+#endif // KJS_PURE_ECMA
+
 // ------------------------------ StringObjectImp ------------------------------
 
 StringObjectImp::StringObjectImp(ExecState* exec,
@@ -849,4 +1058,4 @@ JSValue *StringObjectFuncImp::callAsFunction(ExecState *exec, JSObject* /*thisOb
   return jsString(s);
 }
 
-}
+} // namespace KJS
index 6c4c80086e107433e9ae1b1a319cc11a6dbf5837..ad3c52a64303e0445d0e4d979fedee2d68fae521 100644 (file)
@@ -25,6 +25,7 @@
 #include "function_object.h"
 #include "JSWrapperObject.h"
 #include "internal.h"
+#include "lookup.h"
 
 namespace KJS {
 
@@ -80,27 +81,53 @@ namespace KJS {
   /**
    * @internal
    *
-   * Class to implement all methods that are properties of the
+   * Classes to implement all methods that are properties of the
    * String.prototype object
    */
-  class StringProtoFunc : public InternalFunctionImp {
-  public:
-    StringProtoFunc(ExecState *exec, int i, int len, const Identifier&);
-
-    virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-
-    enum { ToString, ValueOf, CharAt, CharCodeAt, Concat, IndexOf, LastIndexOf,
-           Match, Replace, Search, Slice, Split,
-           Substr, Substring, FromCharCode, ToLowerCase, ToUpperCase,
-           ToLocaleLowerCase, ToLocaleUpperCase, LocaleCompare
+#define FOR_EACH_CLASS(macro) \
+    macro(StringProtoFuncToString) \
+    macro(StringProtoFuncValueOf) \
+    macro(StringProtoFuncCharAt) \
+    macro(StringProtoFuncCharCodeAt) \
+    macro(StringProtoFuncConcat) \
+    macro(StringProtoFuncIndexOf) \
+    macro(StringProtoFuncLastIndexOf) \
+    macro(StringProtoFuncMatch) \
+    macro(StringProtoFuncReplace) \
+    macro(StringProtoFuncSearch) \
+    macro(StringProtoFuncSlice) \
+    macro(StringProtoFuncSplit) \
+    macro(StringProtoFuncSubstr) \
+    macro(StringProtoFuncSubstring) \
+    macro(StringProtoFuncToLowerCase) \
+    macro(StringProtoFuncToUpperCase) \
+    macro(StringProtoFuncToLocaleLowerCase) \
+    macro(StringProtoFuncToLocaleUpperCase) \
+    macro(StringProtoFuncLocaleCompare) \
+
+#define FOR_EACH_CLASS_NOT_PURE_ECMA(macro) \
+    macro(StringProtoFuncBig) \
+    macro(StringProtoFuncSmall) \
+    macro(StringProtoFuncBlink) \
+    macro(StringProtoFuncBold) \
+    macro(StringProtoFuncFixed) \
+    macro(StringProtoFuncItalics) \
+    macro(StringProtoFuncStrike) \
+    macro(StringProtoFuncSub) \
+    macro(StringProtoFuncSup) \
+    macro(StringProtoFuncFontcolor) \
+    macro(StringProtoFuncFontsize) \
+    macro(StringProtoFuncAnchor) \
+    macro(StringProtoFuncLink) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
 #ifndef KJS_PURE_ECMA
-           , Big, Small, Blink, Bold, Fixed, Italics, Strike, Sub, Sup,
-           Fontcolor, Fontsize, Anchor, Link
+FOR_EACH_CLASS_NOT_PURE_ECMA(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
 #endif
-    };
-  private:
-    int id;
-  };
+
+#undef FOR_EACH_CLASS
+#undef FOR_EACH_CLASS_NOT_PURE_ECMA
+
 
   /**
    * @internal
index 2cc343c2d422fe97d1204e2f221ec8cd28933b03..aa123e237f079fcefc0d25601a227647e833ad35 100644 (file)
@@ -1,3 +1,100 @@
+2007-11-08  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Darin.
+
+        Convert JavaScript internal function objects to use one class per
+        function.  This avoids a switch statement inside what used to be
+        the shared function classes and will allow Shark to better analyze
+        the code.
+
+        To make this switch, the value property of the HashEntry was changed
+        to a union of an intptr_t (which is used to continue handle valueGetters)
+        and function pointer which points to a static constructor for the
+        individual new function objects.
+
+        SunSpider claims this is a 0.5% speedup.
+
+        - On the WebCore side, I updated CodeGeneratorJS.pm to generate the
+          new classes and hand updated the remain non-generated (groan) classes.
+
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::customGetOwnPropertySlot):
+        * bindings/js/JSEventTargetNode.cpp:
+        (WebCore::JSEventTargetNodePrototypeFunctionAddEventListener::callAsFunction):
+        (WebCore::JSEventTargetNodePrototypeFunctionRemoveEventListener::callAsFunction):
+        (WebCore::JSEventTargetNodePrototypeFunctionDispatchEvent::callAsFunction):
+        * bindings/js/JSEventTargetNode.h:
+        * bindings/js/JSHTMLInputElementBase.cpp:
+        (WebCore::JSHTMLInputElementBaseFunctionSetSelectionRange::callAsFunction):
+        (WebCore::JSHTMLInputElementBase::getOwnPropertySlot):
+        * bindings/js/JSHTMLInputElementBase.h:
+        (WebCore::JSHTMLInputElementBase::):
+        * bindings/js/JSXMLHttpRequest.cpp:
+        (KJS::JSXMLHttpRequestPrototypeFunctionAbort::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionGetAllResponseHeaders::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionGetResponseHeader::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionOpen::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionSend::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionSetRequestHeader::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionOverrideMIMEType::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionAddEventListener::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionRemoveEventListener::callAsFunction):
+        (KJS::JSXMLHttpRequestPrototypeFunctionDispatchEvent::callAsFunction):
+        * bindings/js/JSXMLHttpRequest.h:
+        (KJS::JSXMLHttpRequest::impl):
+        * bindings/js/JSXSLTProcessor.cpp:
+        (KJS::JSXSLTProcessorPrototypeFunctionImportStylesheet::callAsFunction):
+        (KJS::JSXSLTProcessorPrototypeFunctionTransformToFragment::callAsFunction):
+        (KJS::JSXSLTProcessorPrototypeFunctionTransformToDocument::callAsFunction):
+        (KJS::JSXSLTProcessorPrototypeFunctionSetParameter::callAsFunction):
+        (KJS::JSXSLTProcessorPrototypeFunctionGetParameter::callAsFunction):
+        (KJS::JSXSLTProcessorPrototypeFunctionRemoveParameter::callAsFunction):
+        (KJS::JSXSLTProcessorPrototypeFunctionClearParameters::callAsFunction):
+        (KJS::JSXSLTProcessorPrototypeFunctionReset::callAsFunction):
+        * bindings/js/JSXSLTProcessor.h:
+        * bindings/js/kjs_events.cpp:
+        (WebCore::JSClipboardPrototypeFunctionClearData::callAsFunction):
+        (WebCore::JSClipboardPrototypeFunctionGetData::callAsFunction):
+        (WebCore::JSClipboardPrototypeFunctionSetData::callAsFunction):
+        (WebCore::JSClipboardPrototypeFunctionSetDragImage::callAsFunction):
+        * bindings/js/kjs_events.h:
+        * bindings/js/kjs_navigator.cpp:
+        (KJS::Plugins::):
+        (KJS::Navigator::getOwnPropertySlot):
+        (KJS::Plugins::getOwnPropertySlot):
+        (KJS::PluginsFunctionRefresh::callAsFunction):
+        (KJS::NavigatorProtoFuncJavaEnabled::callAsFunction):
+        * bindings/js/kjs_navigator.h:
+        (KJS::Navigator::):
+        * bindings/js/kjs_window.cpp:
+        (KJS::Window::getOwnPropertySlot):
+        (KJS::Window::put):
+        (KJS::WindowProtoFuncAToB::callAsFunction):
+        (KJS::WindowProtoFuncBToA::callAsFunction):
+        (KJS::WindowProtoFuncOpen::callAsFunction):
+        (KJS::WindowProtoFuncScrollBy::callAsFunction):
+        (KJS::WindowProtoFuncScrollTo::callAsFunction):
+        (KJS::WindowProtoFuncMoveBy::callAsFunction):
+        (KJS::WindowProtoFuncMoveTo::callAsFunction):
+        (KJS::WindowProtoFuncResizeBy::callAsFunction):
+        (KJS::WindowProtoFuncResizeTo::callAsFunction):
+        (KJS::WindowProtoFuncSetTimeout::callAsFunction):
+        (KJS::WindowProtoFuncClearTimeout::callAsFunction):
+        (KJS::WindowProtoFuncSetInterval::callAsFunction):
+        (KJS::WindowProtoFuncAddEventListener::callAsFunction):
+        (KJS::WindowProtoFuncRemoveEventListener::callAsFunction):
+        (KJS::WindowProtoFuncShowModalDialog::callAsFunction):
+        (KJS::WindowProtoFuncNotImplemented::callAsFunction):
+        (KJS::Location::getOwnPropertySlot):
+        (KJS::Location::put):
+        (KJS::LocationProtoFuncReplace::callAsFunction):
+        (KJS::LocationProtoFuncReload::callAsFunction):
+        (KJS::LocationProtoFuncAssign::callAsFunction):
+        (KJS::LocationProtoFuncToString::callAsFunction):
+        * bindings/js/kjs_window.h:
+        (KJS::Window::):
+        * bindings/scripts/CodeGeneratorJS.pm:
+
 2007-11-08  Mark Rowe  <mrowe@apple.com>
 
         Fix the Gtk, Qt and Wx builds.
index d35444a4d6444109357b2ac64845b1b23c8b9d50..479965f5aef1d26aada900ba711ff72aec1d291a 100644 (file)
@@ -43,7 +43,7 @@ bool JSDOMWindow::customGetOwnPropertySlot(KJS::ExecState* exec, const KJS::Iden
                 const KJS::HashEntry* entry = KJS::Lookup::findEntry(static_cast<KJS::JSObject*>(proto)->classInfo()->propHashTable, propertyName);
                 ASSERT(entry);
                 if (entry) {
-                    slot.setStaticEntry(this, entry, KJS::staticFunctionGetter<JSDOMWindowPrototypeFunction>);
+                    slot.setStaticEntry(this, entry, KJS::staticFunctionGetter);
                     return true;
                 }
             }
@@ -76,19 +76,17 @@ bool JSDOMWindow::customGetOwnPropertySlot(KJS::ExecState* exec, const KJS::Iden
         const KJS::HashEntry* entry = KJS::Lookup::findEntry(static_cast<KJS::JSObject*>(proto)->classInfo()->propHashTable, propertyName);
         if (entry) {
             if (entry->attr & KJS::Function) {
-                switch (entry->value) {
-                    case FocusFuncNum:
-                    case BlurFuncNum:
-                    case CloseFuncNum:
-                        slot.setStaticEntry(this, entry, KJS::staticFunctionGetter<JSDOMWindowPrototypeFunction>);
-                        return true;
-                    default:
-                        if (!isSafeScript(exec))
-                            slot.setUndefined(this);
-                        else
-                            slot.setStaticEntry(this, entry, KJS::staticFunctionGetter<JSDOMWindowPrototypeFunction>);
-                        return true;
+                if (entry->value.functionValue == &JSDOMWindowPrototypeFunctionFocus::create
+                    || entry->value.functionValue == &JSDOMWindowPrototypeFunctionBlur::create
+                    || entry->value.functionValue == &JSDOMWindowPrototypeFunctionClose::create)
+                        slot.setStaticEntry(this, entry, KJS::staticFunctionGetter);
+                else {
+                    if (!isSafeScript(exec))
+                        slot.setUndefined(this);
+                    else
+                        slot.setStaticEntry(this, entry, KJS::staticFunctionGetter);
                 }
+                return true;
             }
         }
     }
index 0f42ae0eb00f7d3cb00e3b8525ef81c6b62f6d21..71ebcbcfc7a4f760fcbed355e56199cecd9a2fd4 100644 (file)
@@ -344,48 +344,58 @@ void JSEventTargetNode::pushEventHandlerScope(ExecState*, ScopeChain&) const
 /*
 @begin JSEventTargetNodePrototypeTable 5
 # from the EventTarget interface
-addEventListener        WebCore::JSEventTargetNode::AddEventListener   DontDelete|Function 3
-removeEventListener     WebCore::JSEventTargetNode::RemoveEventListener    DontDelete|Function 3
-dispatchEvent           WebCore::JSEventTargetNode::DispatchEvent  DontDelete|Function 1
+addEventListener        &WebCore::JSEventTargetNodePrototypeFunctionAddEventListener::create    DontDelete|Function 3
+removeEventListener     &WebCore::JSEventTargetNodePrototypeFunctionRemoveEventListener::create DontDelete|Function 3
+dispatchEvent           &WebCore::JSEventTargetNodePrototypeFunctionDispatchEvent::create       DontDelete|Function 1
 @end
 */
 
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(JSEventTargetNodePrototypeFunction)
-KJS_IMPLEMENT_PROTOTYPE("EventTargetNode", JSEventTargetNodePrototype, JSEventTargetNodePrototypeFunction)
+KJS_IMPLEMENT_PROTOTYPE("EventTargetNode", JSEventTargetNodePrototype)
 
-JSValue* JSEventTargetNodePrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+JSValue* JSEventTargetNodePrototypeFunctionAddEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSEventTargetNode::info))
+        return throwError(exec, TypeError);
+    DOMExceptionTranslator exception(exec);
+    JSEventTargetNode* jsNode = static_cast<JSEventTargetNode*>(thisObj);
+    EventTargetNode* node = static_cast<EventTargetNode*>(jsNode->impl());
+
+    Frame* frame = node->document()->frame();
+    if (!frame)
+        return jsUndefined();
+    JSEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSEventListener(args[1]);
+    if (listener)
+        node->addEventListener(args[0]->toString(exec), listener,args[2]->toBoolean(exec));
+    return jsUndefined();
+}
+
+JSValue* JSEventTargetNodePrototypeFunctionRemoveEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
     if (!thisObj->inherits(&JSEventTargetNode::info))
         return throwError(exec, TypeError);
     DOMExceptionTranslator exception(exec);
     JSEventTargetNode* jsNode = static_cast<JSEventTargetNode*>(thisObj);
     EventTargetNode* node = static_cast<EventTargetNode*>(jsNode->impl());
-    switch (id) {
-        case JSEventTargetNode::AddEventListener: {
-            Frame* frame = node->document()->frame();
-            if (!frame)
-                return jsUndefined();
-            JSEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSEventListener(args[1]);
-            if (listener)
-                node->addEventListener(args[0]->toString(exec), listener,args[2]->toBoolean(exec));
-            return jsUndefined();
-        }
-        case JSEventTargetNode::RemoveEventListener: {
-            Frame* frame = node->document()->frame();
-            if (!frame)
-                return jsUndefined();
-            JSEventListener* listener = KJS::Window::retrieveWindow(frame)->findJSEventListener(args[1]);
-            if (listener) 
-                node->removeEventListener(args[0]->toString(exec), listener,args[2]->toBoolean(exec));
-            return jsUndefined();
-        }
-        case JSEventTargetNode::DispatchEvent:
-            return jsBoolean(node->dispatchEvent(toEvent(args[0]), exception));
-    }
 
+    Frame* frame = node->document()->frame();
+    if (!frame)
+        return jsUndefined();
+    JSEventListener* listener = KJS::Window::retrieveWindow(frame)->findJSEventListener(args[1]);
+    if (listener) 
+        node->removeEventListener(args[0]->toString(exec), listener,args[2]->toBoolean(exec));
     return jsUndefined();
 }
 
+JSValue* JSEventTargetNodePrototypeFunctionDispatchEvent::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSEventTargetNode::info))
+        return throwError(exec, TypeError);
+    DOMExceptionTranslator exception(exec);
+    JSEventTargetNode* jsNode = static_cast<JSEventTargetNode*>(thisObj);
+    EventTargetNode* node = static_cast<EventTargetNode*>(jsNode->impl());
+    
+    return jsBoolean(node->dispatchEvent(toEvent(args[0]), exception));
+}
 
 EventTargetNode* toEventTargetNode(JSValue* val)
 {
index 7ca442a1d77338f930717b7dee16de7983d5e341..c0b790b5dc82372888ea811ddf1e8155c720007a 100644 (file)
@@ -61,6 +61,14 @@ namespace WebCore {
 
     KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(JSEventTargetNodePrototype, JSNodePrototype)
 
+#define FOR_EACH_CLASS(macro) \
+    macro(JSEventTargetNodePrototypeFunctionAddEventListener) \
+    macro(JSEventTargetNodePrototypeFunctionRemoveEventListener) \
+    macro(JSEventTargetNodePrototypeFunctionDispatchEvent) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
 } // namespace WebCore
 
 #endif // JSEventTargetNode_h
index b04f9d4f30ef52425f27d7a57a52b0276e6136d7..7b4a3489bab1ec01f668eb0b8054a46643b8b4f8 100644 (file)
@@ -36,42 +36,22 @@ namespace WebCore {
 @begin JSHTMLInputElementBasePrototypeTable 0
 @end
 @begin JSHTMLInputElementBaseFunctionTable 1
-  setSelectionRange     WebCore::JSHTMLInputElementBase::SetSelectionRange         DontDelete|Function 2
+  setSelectionRange     &WebCore::JSHTMLInputElementBaseFunctionSetSelectionRange::create         DontDelete|Function 2
 @end
 */
 
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(JSHTMLInputElementBasePrototypeFunction)
-KJS_IMPLEMENT_PROTOTYPE("JSHTMLInputElementBase", JSHTMLInputElementBasePrototype, JSHTMLInputElementBasePrototypeFunction)
+KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE(JSHTMLInputElementBasePrototypeFunction)
+KJS_IMPLEMENT_PROTOTYPE("JSHTMLInputElementBase", JSHTMLInputElementBasePrototype)
 
 JSValue* JSHTMLInputElementBasePrototypeFunction::callAsFunction(ExecState*, JSObject*, const List&)
 {
     return 0;
 }
 
-// SetSelectionRange is implemented on the class instead of on the prototype
-// to make it easier to enable/disable lookup of the function based on input type.
-class JSHTMLInputElementBaseFunction : public InternalFunctionImp {
-public:
-    JSHTMLInputElementBaseFunction(ExecState*, int i, int len, const Identifier& name);
-    virtual JSValue *callAsFunction(ExecState*, JSObject* thisObj, const List& args);
-private:
-    int m_id;
-};
-
-JSHTMLInputElementBaseFunction::JSHTMLInputElementBaseFunction(ExecState* exec, int i, int len, const Identifier& name)
-    : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
-    , m_id(i)
-{
-    put(exec, exec->propertyNames().length, jsNumber(len), DontDelete|ReadOnly|DontEnum);
-}
-
-JSValue* JSHTMLInputElementBaseFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+JSValue* JSHTMLInputElementBaseFunctionSetSelectionRange::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
     HTMLInputElement& input = *static_cast<HTMLInputElement*>(static_cast<JSHTMLInputElementBase*>(thisObj)->impl());
-    if (m_id == JSHTMLInputElementBase::SetSelectionRange) {
-        input.setSelectionRange(args[0]->toInt32(exec), args[1]->toInt32(exec));
-        return jsUndefined();
-    }
+    input.setSelectionRange(args[0]->toInt32(exec), args[1]->toInt32(exec));
     return jsUndefined();
 }
 
@@ -94,8 +74,8 @@ bool JSHTMLInputElementBase::getOwnPropertySlot(ExecState* exec, const Identifie
     
     // otherwise, do our own function lookup on our function table
     const HashEntry* entry = Lookup::findEntry(&JSHTMLInputElementBaseFunctionTable, propertyName);
-    if (entry && (entry->value == SetSelectionRange)) {
-        slot.setStaticEntry(this, entry, staticFunctionGetter<JSHTMLInputElementBaseFunction>); 
+    if (entry && (entry->attr & KJS::Function) && entry->value.functionValue == &WebCore::JSHTMLInputElementBaseFunctionSetSelectionRange::create) {
+        slot.setStaticEntry(this, entry, staticFunctionGetter); 
         return true;
     }
     ASSERT(!entry);
index 2bc372a8c1b2bdb0730ee377fc2f08121aaf4161..7d2b7bd46da81541260ea063807d514abb6505c8 100644 (file)
@@ -39,9 +39,13 @@ namespace WebCore {
         void putValueProperty(KJS::ExecState*, int token, KJS::JSValue*, int attr);
         virtual const KJS::ClassInfo* classInfo() const { return &info; }
         static const KJS::ClassInfo info;
-        enum { SetSelectionRange, SelectionStart, SelectionEnd };
+        enum { SelectionStart, SelectionEnd };
     };
 
+    // SetSelectionRange is implemented on the class instead of on the prototype
+    // to make it easier to enable/disable lookup of the function based on input type.
+    KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE(JSHTMLInputElementBaseFunctionSetSelectionRange)
+
 } // namespace WebCore
 
 #endif // JSHTMLInputElementBase_h
index 9749496eed4a73441a8be62ca2887b8aab8e10bd..a5e96bf0c815800a609464e46e333c7835179865 100644 (file)
@@ -41,23 +41,22 @@ using namespace WebCore;
 
 /* Source for JSXMLHttpRequestPrototypeTable.
 @begin JSXMLHttpRequestPrototypeTable 7
-  abort                 JSXMLHttpRequest::Abort                   DontDelete|Function 0
-  getAllResponseHeaders JSXMLHttpRequest::GetAllResponseHeaders   DontDelete|Function 0
-  getResponseHeader     JSXMLHttpRequest::GetResponseHeader       DontDelete|Function 1
-  open                  JSXMLHttpRequest::Open                    DontDelete|Function 5
-  overrideMimeType      JSXMLHttpRequest::OverrideMIMEType        DontDelete|Function 1
-  send                  JSXMLHttpRequest::Send                    DontDelete|Function 1
-  setRequestHeader      JSXMLHttpRequest::SetRequestHeader        DontDelete|Function 2
+  abort                 &JSXMLHttpRequestPrototypeFunctionAbort::create                   DontDelete|Function 0
+  getAllResponseHeaders &JSXMLHttpRequestPrototypeFunctionGetAllResponseHeaders::create   DontDelete|Function 0
+  getResponseHeader     &JSXMLHttpRequestPrototypeFunctionGetResponseHeader::create       DontDelete|Function 1
+  open                  &JSXMLHttpRequestPrototypeFunctionOpen::create                    DontDelete|Function 5
+  overrideMimeType      &JSXMLHttpRequestPrototypeFunctionOverrideMIMEType::create        DontDelete|Function 1
+  send                  &JSXMLHttpRequestPrototypeFunctionSend::create                    DontDelete|Function 1
+  setRequestHeader      &JSXMLHttpRequestPrototypeFunctionSetRequestHeader::create        DontDelete|Function 2
 # from the EventTarget interface
 # FIXME: add DOM3 EventTarget methods (addEventListenerNS, removeEventListenerNS).
-  addEventListener      JSXMLHttpRequest::AddEventListener        DontDelete|Function 3
-  removeEventListener   JSXMLHttpRequest::RemoveEventListener     DontDelete|Function 3
-  dispatchEvent         JSXMLHttpRequest::DispatchEvent           DontDelete|Function 1
+  addEventListener      &JSXMLHttpRequestPrototypeFunctionAddEventListener::create        DontDelete|Function 3
+  removeEventListener   &JSXMLHttpRequestPrototypeFunctionRemoveEventListener::create     DontDelete|Function 3
+  dispatchEvent         &JSXMLHttpRequestPrototypeFunctionDispatchEvent::create           DontDelete|Function 1
 @end
 */
 KJS_DEFINE_PROTOTYPE(JSXMLHttpRequestPrototype)
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(JSXMLHttpRequestPrototypeFunction)
-KJS_IMPLEMENT_PROTOTYPE("JSXMLHttpRequest", JSXMLHttpRequestPrototype, JSXMLHttpRequestPrototypeFunction)
+KJS_IMPLEMENT_PROTOTYPE("JSXMLHttpRequest", JSXMLHttpRequestPrototype)
 
 JSXMLHttpRequestConstructorImp::JSXMLHttpRequestConstructorImp(ExecState* exec, Document* d)
     : doc(d)
@@ -204,131 +203,194 @@ JSXMLHttpRequest::~JSXMLHttpRequest()
     ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-JSValue* JSXMLHttpRequestPrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+JSValue* JSXMLHttpRequestPrototypeFunctionAbort::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
     if (!thisObj->inherits(&JSXMLHttpRequest::info))
         return throwError(exec, TypeError);
 
     JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
 
+    request->impl()->abort();
+    return jsUndefined();
+}
+
+JSValue* JSXMLHttpRequestPrototypeFunctionGetAllResponseHeaders::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
     ExceptionCode ec = 0;
 
-    switch (id) {
-        case JSXMLHttpRequest::Abort:
-            request->m_impl->abort();
-            return jsUndefined();
+    JSValue* headers = jsStringOrUndefined(request->impl()->getAllResponseHeaders(ec));
+    setDOMException(exec, ec);
+    return headers;
+}
 
-        case JSXMLHttpRequest::GetAllResponseHeaders: {
-            JSValue* headers = jsStringOrUndefined(request->m_impl->getAllResponseHeaders(ec));
-            setDOMException(exec, ec);
-            return headers;
-        }
-        case JSXMLHttpRequest::GetResponseHeader: {
-            if (args.size() < 1)
-                return throwError(exec, SyntaxError, "Not enough arguments");
+JSValue* JSXMLHttpRequestPrototypeFunctionGetResponseHeader::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
 
-            JSValue* header = jsStringOrNull(request->m_impl->getResponseHeader(args[0]->toString(exec), ec));
-            setDOMException(exec, ec);
-            return header;
-        }
-        case JSXMLHttpRequest::Open: {
-            if (args.size() < 2)
-                return throwError(exec, SyntaxError, "Not enough arguments");
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+    ExceptionCode ec = 0;
 
-            String method = args[0]->toString(exec);
-            Frame* frame = Window::retrieveActive(exec)->impl()->frame();
-            if (!frame)
-                return jsUndefined();
-            KURL url = frame->loader()->completeURL(DeprecatedString(args[1]->toString(exec)));
+    if (args.size() < 1)
+        return throwError(exec, SyntaxError, "Not enough arguments");
 
-            bool async = true;
-            if (args.size() >= 3)
-                async = args[2]->toBoolean(exec);
+    JSValue* header = jsStringOrNull(request->impl()->getResponseHeader(args[0]->toString(exec), ec));
+    setDOMException(exec, ec);
+    return header;
+}
 
-            if (args.size() >= 4 && !args[3]->isUndefined()) {
-                String user = valueToStringWithNullCheck(exec, args[3]);
 
-                if (args.size() >= 5 && !args[4]->isUndefined()) {
-                    String password = valueToStringWithNullCheck(exec, args[4]);
-                    request->m_impl->open(method, url, async, user, password, ec);
-                } else
-                    request->m_impl->open(method, url, async, user, ec);
-            } else
-                request->m_impl->open(method, url, async, ec);
+JSValue* JSXMLHttpRequestPrototypeFunctionOpen::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
 
-            setDOMException(exec, ec);
-            return jsUndefined();
-        }
-        case JSXMLHttpRequest::Send: {
-            String body;
-
-            if (args.size() >= 1) {
-                if (args[0]->toObject(exec)->inherits(&JSDocument::info)) {
-                    Document* doc = static_cast<Document*>(static_cast<JSDocument*>(args[0]->toObject(exec))->impl());
-                    body = doc->toString().deprecatedString();
-                } else {
-                    // converting certain values (like null) to object can set an exception
-                    if (exec->hadException())
-                        exec->clearException();
-                    else
-                        body = args[0]->toString(exec);
-                }
-            }
-
-            request->m_impl->send(body, ec);
-            setDOMException(exec, ec);
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+    ExceptionCode ec = 0;
 
-            return jsUndefined();
-        }
-        case JSXMLHttpRequest::SetRequestHeader:
-            if (args.size() < 2)
-                return throwError(exec, SyntaxError, "Not enough arguments");
+    if (args.size() < 2)
+        return throwError(exec, SyntaxError, "Not enough arguments");
 
-            request->m_impl->setRequestHeader(args[0]->toString(exec), args[1]->toString(exec), ec);
-            setDOMException(exec, ec);
-            return jsUndefined();
+    String method = args[0]->toString(exec);
+    Frame* frame = Window::retrieveActive(exec)->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+    KURL url = frame->loader()->completeURL(DeprecatedString(args[1]->toString(exec)));
 
-        case JSXMLHttpRequest::OverrideMIMEType:
-            if (args.size() < 1)
-                return throwError(exec, SyntaxError, "Not enough arguments");
+    bool async = true;
+    if (args.size() >= 3)
+        async = args[2]->toBoolean(exec);
 
-            request->m_impl->overrideMIMEType(args[0]->toString(exec));
-            return jsUndefined();
-        
-        case JSXMLHttpRequest::AddEventListener: {
-            Document* doc = request->m_impl->document();
-            if (!doc)
-                return jsUndefined();
-            Frame* frame = doc->frame();
-            if (!frame)
-                return jsUndefined();
-            JSUnprotectedEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(args[1], true);
-            if (!listener)
-                return jsUndefined();
-            request->m_impl->addEventListener(args[0]->toString(exec), listener, args[2]->toBoolean(exec));
-            return jsUndefined();
-        }
-        case JSXMLHttpRequest::RemoveEventListener: {
-            Document* doc = request->m_impl->document();
-            if (!doc)
-                return jsUndefined();
-            Frame* frame = doc->frame();
-            if (!frame)
-                return jsUndefined();
-            JSUnprotectedEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(args[1], true);
-            if (!listener)
-                return jsUndefined();
-            request->m_impl->removeEventListener(args[0]->toString(exec), listener, args[2]->toBoolean(exec));
-            return jsUndefined();
-        }
-        case JSXMLHttpRequest::DispatchEvent: {
-            bool result = request->m_impl->dispatchEvent(toEvent(args[0]), ec);
-            setDOMException(exec, ec);
-            return jsBoolean(result);
+    if (args.size() >= 4 && !args[3]->isUndefined()) {
+        String user = valueToStringWithNullCheck(exec, args[3]);
+
+        if (args.size() >= 5 && !args[4]->isUndefined()) {
+            String password = valueToStringWithNullCheck(exec, args[4]);
+            request->impl()->open(method, url, async, user, password, ec);
+        } else
+            request->impl()->open(method, url, async, user, ec);
+    } else
+        request->impl()->open(method, url, async, ec);
+
+    setDOMException(exec, ec);
+    return jsUndefined();
+}
+
+JSValue* JSXMLHttpRequestPrototypeFunctionSend::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+    ExceptionCode ec = 0;
+
+    String body;
+
+    if (args.size() >= 1) {
+        if (args[0]->toObject(exec)->inherits(&JSDocument::info)) {
+            Document* doc = static_cast<Document*>(static_cast<JSDocument*>(args[0]->toObject(exec))->impl());
+            body = doc->toString().deprecatedString();
+        } else {
+            // converting certain values (like null) to object can set an exception
+            if (exec->hadException())
+                exec->clearException();
+            else
+                body = args[0]->toString(exec);
         }
     }
 
+    request->impl()->send(body, ec);
+    setDOMException(exec, ec);
+
+    return jsUndefined();
+}
+
+JSValue* JSXMLHttpRequestPrototypeFunctionSetRequestHeader::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+    ExceptionCode ec = 0;
+
+    if (args.size() < 2)
+        return throwError(exec, SyntaxError, "Not enough arguments");
+
+    request->impl()->setRequestHeader(args[0]->toString(exec), args[1]->toString(exec), ec);
+    setDOMException(exec, ec);
+    return jsUndefined();
+
+}
+
+JSValue* JSXMLHttpRequestPrototypeFunctionOverrideMIMEType::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+
+    if (args.size() < 1)
+        return throwError(exec, SyntaxError, "Not enough arguments");
+
+    request->impl()->overrideMIMEType(args[0]->toString(exec));
+    return jsUndefined();
+}
+
+JSValue* JSXMLHttpRequestPrototypeFunctionAddEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+
+    Document* doc = request->impl()->document();
+    if (!doc)
+        return jsUndefined();
+    Frame* frame = doc->frame();
+    if (!frame)
+        return jsUndefined();
+    JSUnprotectedEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(args[1], true);
+    if (!listener)
+        return jsUndefined();
+    request->impl()->addEventListener(args[0]->toString(exec), listener, args[2]->toBoolean(exec));
     return jsUndefined();
 }
 
+JSValue* JSXMLHttpRequestPrototypeFunctionRemoveEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+
+    Document* doc = request->impl()->document();
+    if (!doc)
+        return jsUndefined();
+    Frame* frame = doc->frame();
+    if (!frame)
+        return jsUndefined();
+    JSUnprotectedEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(args[1], true);
+    if (!listener)
+        return jsUndefined();
+    request->impl()->removeEventListener(args[0]->toString(exec), listener, args[2]->toBoolean(exec));
+    return jsUndefined();
+}
+
+JSValue* JSXMLHttpRequestPrototypeFunctionDispatchEvent::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+    ExceptionCode ec = 0;
+
+    bool result = request->impl()->dispatchEvent(toEvent(args[0]), ec);
+    setDOMException(exec, ec);
+    return jsBoolean(result);
+}
+
 } // end namespace
index d2b5416766a5564657eebb543660ff93b6c4be18..6afb608fc9db6c749f5dfc2fa93e077d40602b53 100644 (file)
@@ -59,11 +59,27 @@ public:
     virtual bool toBoolean(ExecState*) const { return true; }
     virtual void mark();
 
+    WebCore::XMLHttpRequest* impl() const { return m_impl.get(); }
+
 private:
-    friend class JSXMLHttpRequestPrototypeFunction;
     RefPtr<WebCore::XMLHttpRequest> m_impl;
 };
 
+#define FOR_EACH_CLASS(macro) \
+    macro(JSXMLHttpRequestPrototypeFunctionAbort) \
+    macro(JSXMLHttpRequestPrototypeFunctionGetAllResponseHeaders) \
+    macro(JSXMLHttpRequestPrototypeFunctionGetResponseHeader) \
+    macro(JSXMLHttpRequestPrototypeFunctionOpen) \
+    macro(JSXMLHttpRequestPrototypeFunctionSend) \
+    macro(JSXMLHttpRequestPrototypeFunctionSetRequestHeader) \
+    macro(JSXMLHttpRequestPrototypeFunctionOverrideMIMEType) \
+    macro(JSXMLHttpRequestPrototypeFunctionAddEventListener) \
+    macro(JSXMLHttpRequestPrototypeFunctionRemoveEventListener) \
+    macro(JSXMLHttpRequestPrototypeFunctionDispatchEvent) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
 } // namespace
 
 #endif
index 7ef90b41dfd0f5b18d33c90d9050ab962a70191c..6da8bfde3c0c8bff465776ad466865e88178db75 100644 (file)
@@ -44,20 +44,19 @@ const ClassInfo JSXSLTProcessor::info = { "XSLTProcessor", 0, 0 };
 
 /*
 @begin XSLTProcessorPrototypeTable 7
-  importStylesheet      JSXSLTProcessor::ImportStylesheet     DontDelete|Function 1
-  transformToFragment   JSXSLTProcessor::TransformToFragment  DontDelete|Function 2
-  transformToDocument   JSXSLTProcessor::TransformToDocument  DontDelete|Function 2
-  setParameter          JSXSLTProcessor::SetParameter         DontDelete|Function 3
-  getParameter          JSXSLTProcessor::GetParameter         DontDelete|Function 2
-  removeParameter       JSXSLTProcessor::RemoveParameter      DontDelete|Function 2
-  clearParameters       JSXSLTProcessor::ClearParameters      DontDelete|Function 0
-  reset                 JSXSLTProcessor::Reset                DontDelete|Function 0
+  importStylesheet      &JSXSLTProcessorPrototypeFunctionImportStylesheet::create     DontDelete|Function 1
+  transformToFragment   &JSXSLTProcessorPrototypeFunctionTransformToFragment::create  DontDelete|Function 2
+  transformToDocument   &JSXSLTProcessorPrototypeFunctionTransformToDocument::create  DontDelete|Function 2
+  setParameter          &JSXSLTProcessorPrototypeFunctionSetParameter::create         DontDelete|Function 3
+  getParameter          &JSXSLTProcessorPrototypeFunctionGetParameter::create         DontDelete|Function 2
+  removeParameter       &JSXSLTProcessorPrototypeFunctionRemoveParameter::create      DontDelete|Function 2
+  clearParameters       &JSXSLTProcessorPrototypeFunctionClearParameters::create      DontDelete|Function 0
+  reset                 &JSXSLTProcessorPrototypeFunctionReset::create                DontDelete|Function 0
 @end
 */
 
 KJS_DEFINE_PROTOTYPE(XSLTProcessorPrototype)
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(XSLTProcessorPrototypeFunction)
-KJS_IMPLEMENT_PROTOTYPE("XSLTProcessor", XSLTProcessorPrototype, XSLTProcessorPrototypeFunction)
+KJS_IMPLEMENT_PROTOTYPE("XSLTProcessor", XSLTProcessorPrototype)
 
 JSXSLTProcessor::JSXSLTProcessor(ExecState *exec) : m_impl(new XSLTProcessor())
 {
@@ -69,85 +68,119 @@ JSXSLTProcessor::~JSXSLTProcessor()
     ScriptInterpreter::forgetDOMObject(m_impl.get());
 }
 
-JSValue *XSLTProcessorPrototypeFunction::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
+JSValue* JSXSLTProcessorPrototypeFunctionImportStylesheet::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
     if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
         return throwError(exec, TypeError);
-    XSLTProcessor &processor = *static_cast<JSXSLTProcessor *>(thisObj)->impl();
-    switch (id) {
-        case JSXSLTProcessor::ImportStylesheet:
-        {
-            JSValue *nodeVal = args[0];
-            if (nodeVal->isObject(&JSNode::info)) {
-                JSNode* node = static_cast<JSNode*>(nodeVal);
-                processor.importStylesheet(node->impl());
-                return jsUndefined();
-            }
-            // Throw exception?
-            break;
-        }
-        case JSXSLTProcessor::TransformToFragment:
-        {
-            JSValue *nodeVal = args[0];
-            JSValue *docVal = args[1];
-            if (nodeVal->isObject(&JSNode::info) && docVal->isObject(&JSDocument::info)) {
-                Node* node = static_cast<JSNode*>(nodeVal)->impl();
-                Document* doc = static_cast<Document*>(static_cast<JSDocument *>(docVal)->impl());
-                return toJS(exec, processor.transformToFragment(node, doc).get());
-            }
-            // Throw exception?
-            break;
-        }
-        case JSXSLTProcessor::TransformToDocument:
-        {
-            JSValue *nodeVal = args[0];
-            if (nodeVal->isObject(&JSNode::info)) {
-                JSNode* node = static_cast<JSNode*>(nodeVal);
-                RefPtr<Document> resultDocument = processor.transformToDocument(node->impl());
-                if (resultDocument)
-                    return toJS(exec, resultDocument.get());
-                return jsUndefined();
-            }
-            // Throw exception?
-            break;
-        }
-        case JSXSLTProcessor::SetParameter:
-        {
-            if (args[1]->isUndefinedOrNull() || args[2]->isUndefinedOrNull())
-                return jsUndefined(); // Throw exception?
-            String namespaceURI = args[0]->toString(exec);
-            String localName = args[1]->toString(exec);
-            String value = args[2]->toString(exec);
-            processor.setParameter(namespaceURI, localName, value);
-            return jsUndefined();
-        }
-        case JSXSLTProcessor::GetParameter:
-        {
-            if (args[1]->isUndefinedOrNull())
-                return jsUndefined();
-            String namespaceURI = args[0]->toString(exec);
-            String localName = args[1]->toString(exec);
-            String value = processor.getParameter(namespaceURI, localName);
-            if (!value.isNull())
-                return jsString(value);
-            return jsUndefined();
-        }
-        case JSXSLTProcessor::RemoveParameter:
-        {
-            if (args[1]->isUndefinedOrNull())
-                return jsUndefined();
-            String namespaceURI = args[0]->toString(exec);
-            String localName = args[1]->toString(exec);
-            processor.removeParameter(namespaceURI, localName);
-            return jsUndefined();
-        }
-        case JSXSLTProcessor::ClearParameters:
-            processor.clearParameters();
-            return jsUndefined();
-        case JSXSLTProcessor::Reset:
-            processor.reset();
-            return jsUndefined();
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    JSValue *nodeVal = args[0];
+    if (nodeVal->isObject(&JSNode::info)) {
+        JSNode* node = static_cast<JSNode*>(nodeVal);
+        processor.importStylesheet(node->impl());
+        return jsUndefined();
+    }
+    // Throw exception?
+    return jsUndefined();
+}
+
+JSValue* JSXSLTProcessorPrototypeFunctionTransformToFragment::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
+        return throwError(exec, TypeError);
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    JSValue *nodeVal = args[0];
+    JSValue *docVal = args[1];
+    if (nodeVal->isObject(&JSNode::info) && docVal->isObject(&JSDocument::info)) {
+        Node* node = static_cast<JSNode*>(nodeVal)->impl();
+        Document* doc = static_cast<Document*>(static_cast<JSDocument *>(docVal)->impl());
+        return toJS(exec, processor.transformToFragment(node, doc).get());
+    }
+    // Throw exception?
+    return jsUndefined();
+}
+
+JSValue* JSXSLTProcessorPrototypeFunctionTransformToDocument::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
+        return throwError(exec, TypeError);
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    JSValue *nodeVal = args[0];
+    if (nodeVal->isObject(&JSNode::info)) {
+        JSNode* node = static_cast<JSNode*>(nodeVal);
+        RefPtr<Document> resultDocument = processor.transformToDocument(node->impl());
+        if (resultDocument)
+            return toJS(exec, resultDocument.get());
+        return jsUndefined();
     }
+    // Throw exception?
+    return jsUndefined();
+}
+
+JSValue* JSXSLTProcessorPrototypeFunctionSetParameter::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
+        return throwError(exec, TypeError);
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    if (args[1]->isUndefinedOrNull() || args[2]->isUndefinedOrNull())
+        return jsUndefined(); // Throw exception?
+    String namespaceURI = args[0]->toString(exec);
+    String localName = args[1]->toString(exec);
+    String value = args[2]->toString(exec);
+    processor.setParameter(namespaceURI, localName, value);
+    return jsUndefined();
+}
+
+JSValue* JSXSLTProcessorPrototypeFunctionGetParameter::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
+        return throwError(exec, TypeError);
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    if (args[1]->isUndefinedOrNull())
+        return jsUndefined();
+    String namespaceURI = args[0]->toString(exec);
+    String localName = args[1]->toString(exec);
+    String value = processor.getParameter(namespaceURI, localName);
+    if (!value.isNull())
+        return jsString(value);
+    return jsUndefined();
+}
+
+JSValue* JSXSLTProcessorPrototypeFunctionRemoveParameter::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
+        return throwError(exec, TypeError);
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    if (args[1]->isUndefinedOrNull())
+        return jsUndefined();
+    String namespaceURI = args[0]->toString(exec);
+    String localName = args[1]->toString(exec);
+    processor.removeParameter(namespaceURI, localName);
+    return jsUndefined();
+}
+
+JSValue* JSXSLTProcessorPrototypeFunctionClearParameters::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
+        return throwError(exec, TypeError);
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    processor.clearParameters();
+    return jsUndefined();
+}
+
+JSValue* JSXSLTProcessorPrototypeFunctionReset::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&KJS::JSXSLTProcessor::info))
+        return throwError(exec, TypeError);
+    XSLTProcessor& processor = *static_cast<JSXSLTProcessor*>(thisObj)->impl();
+
+    processor.reset();
     return jsUndefined();
 }
 
index fcf232cfbfe59579faadcc98163ee63a2fa5e28f..d2de4066ba0d1102f33911d990842e149324f9ca 100644 (file)
@@ -47,10 +47,7 @@ public:
     
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
-    
-    enum { ImportStylesheet, TransformToFragment, TransformToDocument, SetParameter,
-            GetParameter, RemoveParameter, ClearParameters, Reset };
-    
+
     WebCore::XSLTProcessor *impl() const { return m_impl.get(); }
 private:
     RefPtr<WebCore::XSLTProcessor> m_impl;
@@ -63,6 +60,19 @@ public:
     virtual JSObject *construct(ExecState *exec, const List &args) { return new JSXSLTProcessor(exec); }
 };
 
+#define FOR_EACH_CLASS(macro) \
+    macro(JSXSLTProcessorPrototypeFunctionImportStylesheet) \
+    macro(JSXSLTProcessorPrototypeFunctionTransformToFragment) \
+    macro(JSXSLTProcessorPrototypeFunctionTransformToDocument) \
+    macro(JSXSLTProcessorPrototypeFunctionSetParameter) \
+    macro(JSXSLTProcessorPrototypeFunctionGetParameter) \
+    macro(JSXSLTProcessorPrototypeFunctionRemoveParameter) \
+    macro(JSXSLTProcessorPrototypeFunctionClearParameters) \
+    macro(JSXSLTProcessorPrototypeFunctionReset) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
 } // namespace KJS
 
 #endif // ENABLE(XSLT)
index da8468d12f3f5e26ec2bcaefbe3327fd06225dfe..17297b9af926d32ac4dba39c80a95ad6e40af609 100644 (file)
@@ -354,21 +354,20 @@ const ClassInfo JSClipboard::info = { "Clipboard", 0, &JSClipboardTable };
 
 /* Source for JSClipboardTable. Use "make hashtables" to regenerate.
 @begin JSClipboardTable 3
-  dropEffect    WebCore::JSClipboard::DropEffect   DontDelete
-  effectAllowed WebCore::JSClipboard::EffectAllowed        DontDelete
-  types         WebCore::JSClipboard::Types        DontDelete|ReadOnly
+  dropEffect    WebCore::JSClipboard::DropEffect                           DontDelete
+  effectAllowed WebCore::JSClipboard::EffectAllowed                        DontDelete
+  types         WebCore::JSClipboard::Types                                DontDelete|ReadOnly
 @end
 @begin JSClipboardPrototypeTable 4
-  clearData     WebCore::JSClipboard::ClearData    DontDelete|Function 0
-  getData       WebCore::JSClipboard::GetData      DontDelete|Function 1
-  setData       WebCore::JSClipboard::SetData      DontDelete|Function 2
-  setDragImage  WebCore::JSClipboard::SetDragImage DontDelete|Function 3
+  clearData     &WebCore::JSClipboardPrototypeFunctionClearData::create    DontDelete|Function 0
+  getData       &WebCore::JSClipboardPrototypeFunctionGetData::create      DontDelete|Function 1
+  setData       &WebCore::JSClipboardPrototypeFunctionSetData::create      DontDelete|Function 2
+  setDragImage  &WebCore::JSClipboardPrototypeFunctionSetDragImage::create DontDelete|Function 3
 @end
 */
 
 KJS_DEFINE_PROTOTYPE(JSClipboardPrototype)
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(JSClipboardPrototypeFunction)
-KJS_IMPLEMENT_PROTOTYPE("Clipboard", JSClipboardPrototype, JSClipboardPrototypeFunction)
+KJS_IMPLEMENT_PROTOTYPE("Clipboard", JSClipboardPrototype)
 
 JSClipboard::JSClipboard(ExecState* exec, Clipboard* clipboard)
     : m_impl(clipboard)
@@ -436,65 +435,82 @@ void JSClipboard::putValueProperty(ExecState* exec, int token, JSValue* value, i
     }
 }
 
-JSValue* JSClipboardPrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+JSValue* JSClipboardPrototypeFunctionClearData::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
     if (!thisObj->inherits(&JSClipboard::info))
         return throwError(exec, TypeError);
 
     Clipboard* clipboard = static_cast<JSClipboard*>(thisObj)->impl();
-    switch (id) {
-        case JSClipboard::ClearData:
-            if (args.size() == 0) {
-                clipboard->clearAllData();
-                return jsUndefined();
-            } else if (args.size() == 1) {
-                clipboard->clearData(args[0]->toString(exec));
-                return jsUndefined();
-            } else
-                return throwError(exec, SyntaxError, "clearData: Invalid number of arguments");
-        case JSClipboard::GetData:
-        {
-            if (args.size() == 1) {
-                bool success;
-                String result = clipboard->getData(args[0]->toString(exec), success);
-                if (success)
-                    return jsString(result);
-                return jsUndefined();
-            } else
-                return throwError(exec, SyntaxError, "getData: Invalid number of arguments");
-        }
-        case JSClipboard::SetData:
-            if (args.size() == 2)
-                return jsBoolean(clipboard->setData(args[0]->toString(exec), args[1]->toString(exec)));
-            return throwError(exec, SyntaxError, "setData: Invalid number of arguments");
-        case JSClipboard::SetDragImage:
-        {
-            if (!clipboard->isForDragging())
-                return jsUndefined();
 
-            if (args.size() != 3)
-                return throwError(exec, SyntaxError, "setDragImage: Invalid number of arguments");
+    if (args.size() == 0) {
+        clipboard->clearAllData();
+        return jsUndefined();
+    } else if (args.size() == 1) {
+        clipboard->clearData(args[0]->toString(exec));
+        return jsUndefined();
+    } else
+        return throwError(exec, SyntaxError, "clearData: Invalid number of arguments");
+}
 
-            int x = args[1]->toInt32(exec);
-            int y = args[2]->toInt32(exec);
+JSValue* JSClipboardPrototypeFunctionGetData::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSClipboard::info))
+        return throwError(exec, TypeError);
 
-            // See if they passed us a node
-            Node* node = toNode(args[0]);
-            if (!node)
-                return throwError(exec, TypeError);
+    Clipboard* clipboard = static_cast<JSClipboard*>(thisObj)->impl();
 
-            if (!node->isElementNode())
-                return throwError(exec, SyntaxError, "setDragImageFromElement: Invalid first argument");
+    if (args.size() == 1) {
+        bool success;
+        String result = clipboard->getData(args[0]->toString(exec), success);
+        if (success)
+            return jsString(result);
+        return jsUndefined();
+    } else
+        return throwError(exec, SyntaxError, "getData: Invalid number of arguments");
+}
 
-            if (static_cast<Element*>(node)->hasLocalName(imgTag) &&
-                !node->inDocument())
-                clipboard->setDragImage(static_cast<HTMLImageElement*>(node)->cachedImage(), IntPoint(x, y));
-            else
-                clipboard->setDragImageElement(node, IntPoint(x, y));
+JSValue* JSClipboardPrototypeFunctionSetData::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSClipboard::info))
+        return throwError(exec, TypeError);
+
+    Clipboard* clipboard = static_cast<JSClipboard*>(thisObj)->impl();
+
+    if (args.size() == 2)
+        return jsBoolean(clipboard->setData(args[0]->toString(exec), args[1]->toString(exec)));
+    return throwError(exec, SyntaxError, "setData: Invalid number of arguments");
+}
+
+JSValue* JSClipboardPrototypeFunctionSetDragImage::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSClipboard::info))
+        return throwError(exec, TypeError);
+
+    Clipboard* clipboard = static_cast<JSClipboard*>(thisObj)->impl();
+
+    if (!clipboard->isForDragging())
+        return jsUndefined();
+
+    if (args.size() != 3)
+        return throwError(exec, SyntaxError, "setDragImage: Invalid number of arguments");
+
+    int x = args[1]->toInt32(exec);
+    int y = args[2]->toInt32(exec);
+
+    // See if they passed us a node
+    Node* node = toNode(args[0]);
+    if (!node)
+        return throwError(exec, TypeError);
+
+    if (!node->isElementNode())
+        return throwError(exec, SyntaxError, "setDragImageFromElement: Invalid first argument");
+
+    if (static_cast<Element*>(node)->hasLocalName(imgTag) &&
+        !node->inDocument())
+        clipboard->setDragImage(static_cast<HTMLImageElement*>(node)->cachedImage(), IntPoint(x, y));
+    else
+        clipboard->setDragImageElement(node, IntPoint(x, y));
 
-            return jsUndefined();
-        }
-    }
     return jsUndefined();
 }
 
index 577d179f21b67f9ae70cd6bb61a274dcd7010e70..545e00246efbd83dcbdea889842b7ddec9d46556 100644 (file)
@@ -121,6 +121,16 @@ namespace WebCore {
     KJS::JSValue* toJS(KJS::ExecState*, Clipboard*);
     Clipboard* toClipboard(KJS::JSValue*);
 
+#define FOR_EACH_CLASS(macro) \
+    macro(JSClipboardPrototypeFunctionClearData) \
+    macro(JSClipboardPrototypeFunctionGetData) \
+    macro(JSClipboardPrototypeFunctionSetData) \
+    macro(JSClipboardPrototypeFunctionSetDragImage) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
+
 } // namespace WebCore
 
 #endif // kjs_events_h
index df87b7ea29fd2e01f2684b746f058ba2e48656e6..651f95c2ca12d272d623adde8f41333adb2feafb 100644 (file)
@@ -89,12 +89,14 @@ namespace KJS {
         JSValue *getValueProperty(ExecState *, int token) const;
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
-        enum { Length, Refresh };
+        enum { Length };
     private:
         static JSValue *indexGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
         static JSValue *nameGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
     };
 
+    KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE(PluginsFunctionRefresh)
+
     class MimeTypes : public PluginBase {
     public:
         MimeTypes(ExecState *exec) : PluginBase(exec) { };
@@ -153,23 +155,22 @@ int KJS::PluginBase::m_plugInCacheRefCount = 0;
 const ClassInfo Navigator::info = { "Navigator", 0, &NavigatorTable };
 /*
 @begin NavigatorTable 13
-  appCodeName   Navigator::AppCodeName  DontDelete|ReadOnly
-  appName       Navigator::AppName      DontDelete|ReadOnly
-  appVersion    Navigator::AppVersion   DontDelete|ReadOnly
-  language      Navigator::Language     DontDelete|ReadOnly
-  userAgent     Navigator::UserAgent    DontDelete|ReadOnly
-  platform      Navigator::Platform     DontDelete|ReadOnly
-  plugins       Navigator::_Plugins     DontDelete|ReadOnly
-  mimeTypes     Navigator::_MimeTypes   DontDelete|ReadOnly
-  product       Navigator::Product      DontDelete|ReadOnly
-  productSub    Navigator::ProductSub   DontDelete|ReadOnly
-  vendor        Navigator::Vendor       DontDelete|ReadOnly
-  vendorSub     Navigator::VendorSub    DontDelete|ReadOnly
-  cookieEnabled Navigator::CookieEnabled DontDelete|ReadOnly
-  javaEnabled   Navigator::JavaEnabled  DontDelete|Function 0
+  appCodeName   Navigator::AppCodeName                  DontDelete|ReadOnly
+  appName       Navigator::AppName                      DontDelete|ReadOnly
+  appVersion    Navigator::AppVersion                   DontDelete|ReadOnly
+  language      Navigator::Language                     DontDelete|ReadOnly
+  userAgent     Navigator::UserAgent                    DontDelete|ReadOnly
+  platform      Navigator::Platform                     DontDelete|ReadOnly
+  plugins       Navigator::_Plugins                     DontDelete|ReadOnly
+  mimeTypes     Navigator::_MimeTypes                   DontDelete|ReadOnly
+  product       Navigator::Product                      DontDelete|ReadOnly
+  productSub    Navigator::ProductSub                   DontDelete|ReadOnly
+  vendor        Navigator::Vendor                       DontDelete|ReadOnly
+  vendorSub     Navigator::VendorSub                    DontDelete|ReadOnly
+  cookieEnabled Navigator::CookieEnabled                DontDelete|ReadOnly
+  javaEnabled   &NavigatorProtoFuncJavaEnabled::create  DontDelete|Function 0
 @end
 */
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(NavigatorFunc)
 
 Navigator::Navigator(ExecState *exec, Frame *f) 
     : m_frame(f)
@@ -179,7 +180,7 @@ Navigator::Navigator(ExecState *exec, Frame *f)
 
 bool Navigator::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
 {
-  return getStaticPropertySlot<NavigatorFunc, Navigator, JSObject>(exec, &NavigatorTable, this, propertyName, slot);
+  return getStaticPropertySlot<Navigator, JSObject>(exec, &NavigatorTable, this, propertyName, slot);
 }
 
 JSValue* Navigator::getValueProperty(ExecState* exec, int token) const
@@ -292,11 +293,10 @@ void PluginBase::refresh(bool reload)
 
 /*
 @begin PluginsTable 2
-  length        Plugins::Length         DontDelete|ReadOnly
-  refresh       Plugins::Refresh        DontDelete|Function 0
+  length        Plugins::Length                        DontDelete|ReadOnly
+  refresh       &PluginsFunctionRefresh::create        DontDelete|Function 0
 @end
 */
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(PluginsFunc)
 
 JSValue *Plugins::getValueProperty(ExecState *exec, int token) const
 {
@@ -326,7 +326,7 @@ bool Plugins::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName
     const HashEntry* entry = Lookup::findEntry(&PluginsTable, propertyName);
     if (entry) {
       if (entry->attr & Function)
-        slot.setStaticEntry(this, entry, staticFunctionGetter<PluginsFunc>);
+        slot.setStaticEntry(this, entry, staticFunctionGetter);
       else
         slot.setStaticEntry(this, entry, staticValueGetter<Plugins>);
       return true;
@@ -531,13 +531,13 @@ bool MimeType::getOwnPropertySlot(ExecState *exec, const Identifier& propertyNam
     return getStaticValueSlot<MimeType, PluginBase>(exec, &MimeTypeTable, this, propertyName, slot);
 }
 
-JSValue *PluginsFunc::callAsFunction(ExecState *exec, JSObject *, const List &args)
+JSValue* PluginsFunctionRefresh::callAsFunction(ExecState* exec, JSObject*, const List& args)
 {
     PluginBase::refresh(args[0]->toBoolean(exec));
     return jsUndefined();
 }
 
-JSValue *NavigatorFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &)
+JSValue* NavigatorProtoFuncJavaEnabled::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
 {
   if (!thisObj->inherits(&KJS::Navigator::info))
     return throwError(exec, TypeError);
index d69416f91d671a3c037d456dc2606b410a7390fd..15fc12ed53ff7e1d5af31dc9e36f02d3c0fcf3f5 100644 (file)
@@ -37,11 +37,14 @@ namespace KJS {
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
     enum { AppCodeName, AppName, AppVersion, Language, UserAgent, Platform,
-           _Plugins, _MimeTypes, Product, ProductSub, Vendor, VendorSub, CookieEnabled, JavaEnabled };
+           _Plugins, _MimeTypes, Product, ProductSub, Vendor, VendorSub, CookieEnabled };
     WebCore::Frame *frame() const { return m_frame; }
   private:
     WebCore::Frame *m_frame;
   };
+
+  KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE(NavigatorProtoFuncJavaEnabled)
+
 } // namespace
 
 #endif
index 519a829c4a88f7878ad4685f0223a96287a01ee3..e26331e6a0ca4c68d77218c499d9f3dcd8625649 100644 (file)
@@ -152,25 +152,27 @@ const ClassInfo Window::info = { "Window", 0, &WindowTable };
 @begin WindowTable 118
 # Warning, when adding a function to this object you need to add a case in Window::get
 # -- Functions --
-  atob                  Window::AToB                DontDelete|Function 1
-  btoa                  Window::BToA                DontDelete|Function 1
-  scroll                Window::Scroll              DontDelete|Function 2
-  scrollBy              Window::ScrollBy            DontDelete|Function 2
-  scrollTo              Window::ScrollTo            DontDelete|Function 2
-  moveBy                Window::MoveBy              DontDelete|Function 2
-  moveTo                Window::MoveTo              DontDelete|Function 2
-  resizeBy              Window::ResizeBy            DontDelete|Function 2
-  resizeTo              Window::ResizeTo            DontDelete|Function 2
-  open                  Window::Open                DontDelete|Function 3
-  setTimeout            Window::SetTimeout          DontDelete|Function 2
-  clearTimeout          Window::ClearTimeout        DontDelete|Function 1
-  setInterval           Window::SetInterval         DontDelete|Function 2
-  clearInterval         Window::ClearInterval       DontDelete|Function 1
-  captureEvents         Window::CaptureEvents       DontDelete|Function 0
-  releaseEvents         Window::ReleaseEvents       DontDelete|Function 0
-  addEventListener      Window::AddEventListener    DontDelete|Function 3
-  removeEventListener   Window::RemoveEventListener DontDelete|Function 3
-  showModalDialog       Window::ShowModalDialog     DontDelete|Function 1
+  atob                  &WindowProtoFuncAToB::create                DontDelete|Function 1
+  btoa                  &WindowProtoFuncBToA::create                DontDelete|Function 1
+  scroll                &WindowProtoFuncScrollTo::create            DontDelete|Function 2
+  scrollBy              &WindowProtoFuncScrollBy::create            DontDelete|Function 2
+  scrollTo              &WindowProtoFuncScrollTo::create            DontDelete|Function 2
+  moveBy                &WindowProtoFuncMoveBy::create              DontDelete|Function 2
+  moveTo                &WindowProtoFuncMoveTo::create              DontDelete|Function 2
+  resizeBy              &WindowProtoFuncResizeBy::create            DontDelete|Function 2
+  resizeTo              &WindowProtoFuncResizeTo::create            DontDelete|Function 2
+  open                  &WindowProtoFuncOpen::create                DontDelete|Function 3
+  setTimeout            &WindowProtoFuncSetTimeout::create          DontDelete|Function 2
+  clearTimeout          &WindowProtoFuncClearTimeout::create        DontDelete|Function 1
+  setInterval           &WindowProtoFuncSetInterval::create         DontDelete|Function 2
+  clearInterval         &WindowProtoFuncClearTimeout::create        DontDelete|Function 1
+  addEventListener      &WindowProtoFuncAddEventListener::create    DontDelete|Function 3
+  removeEventListener   &WindowProtoFuncRemoveEventListener::create DontDelete|Function 3
+  showModalDialog       &WindowProtoFuncShowModalDialog::create     DontDelete|Function 1
+# Not implemented
+  captureEvents         &WindowProtoFuncNotImplemented::create      DontDelete|Function 0
+  releaseEvents         &WindowProtoFuncNotImplemented::create      DontDelete|Function 0
+
 # -- Attributes --
   crypto                Window::Crypto              DontDelete|ReadOnly
   event                 Window::Event_              DontDelete
@@ -666,17 +668,14 @@ bool Window::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName,
   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
   if (entry) {
     if (entry->attr & Function) {
-      switch (entry->value) {
-      case ShowModalDialog:
+      if (entry->value.functionValue == &WindowProtoFuncShowModalDialog::create) {
         if (!canShowModalDialog(this))
           return false;
-        // fall through
-      default:
-        if (isSafeScript(exec))
-          slot.setStaticEntry(this, entry, staticFunctionGetter<WindowFunc>);
-        else
-          slot.setUndefined(this);
-      } 
+      }
+      if (isSafeScript(exec))
+        slot.setStaticEntry(this, entry, staticFunctionGetter);
+      else
+        slot.setUndefined(this);
     } else
       slot.setStaticEntry(this, entry, staticValueGetter<Window>);
     return true;
@@ -728,7 +727,7 @@ void Window::put(ExecState* exec, const Identifier& propertyName, JSValue* value
     if (entry->attr & ReadOnly)
       return;
 
-    switch (entry->value) {
+    switch (entry->value.intValue) {
     case Location_: {
       Frame* p = Window::retrieveActive(exec)->impl()->frame();
       if (p) {
@@ -1233,25 +1232,18 @@ static void adjustWindowRect(const FloatRect& screen, FloatRect& window, const F
     window.setY(window.y() + screen.y());
 }
 
-JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
+JSValue* WindowProtoFuncAToB::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
-  if (!thisObj->inherits(&Window::info))
-    return throwError(exec, TypeError);
-  Window *window = static_cast<Window *>(thisObj);
-  Frame *frame = window->impl()->frame();
-  if (!frame)
-    return jsUndefined();
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
 
-  FrameView *widget = frame->view();
-  Page* page = frame->page();
-  JSValue *v = args[0];
-  UString s = v->toString(exec);
-  String str = s;
-  String str2;
+    JSValue* v = args[0];
+    UString s = v->toString(exec);
 
-  switch (id) {
-  case Window::AToB:
-  case Window::BToA: {
     if (args.size() < 1)
         return throwError(exec, SyntaxError, "Not enough arguments");
     if (v->isNull())
@@ -1266,78 +1258,152 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
         in[i] = static_cast<char>(s.data()[i].unicode());
     Vector<char> out;
 
-    if (id == Window::AToB) {
-        if (!base64Decode(in, out))
-            return throwError(exec, GeneralError, "Cannot decode base64");
-    } else
-        base64Encode(in, out);
+    if (!base64Decode(in, out))
+        return throwError(exec, GeneralError, "Cannot decode base64");
     
     return jsString(String(out.data(), out.size()));
-  }
-  case Window::Open:
-  {
-      String urlString = valueToStringWithUndefinedOrNullCheck(exec, args[0]);
-      AtomicString frameName = args[1]->isUndefinedOrNull() ? "_blank" : AtomicString(args[1]->toString(exec));
-
-      // Because FrameTree::find() returns true for empty strings, we must check for empty framenames.
-      // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
-      if (!allowPopUp(exec, window) && (frameName.isEmpty() || !frame->tree()->find(frameName)))
-          return jsUndefined();
-      
-      // Get the target frame for the special cases of _top and _parent
-      if (frameName == "_top")
-          while (frame->tree()->parent())
-                frame = frame->tree()->parent();
-      else if (frameName == "_parent")
-          if (frame->tree()->parent())
+}
+
+JSValue* WindowProtoFuncBToA::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    JSValue* v = args[0];
+    UString s = v->toString(exec);
+
+    if (args.size() < 1)
+        return throwError(exec, SyntaxError, "Not enough arguments");
+    if (v->isNull())
+        return jsString();
+    if (!s.is8Bit()) {
+        setDOMException(exec, INVALID_CHARACTER_ERR);
+        return jsUndefined();
+    }
+    
+    Vector<char> in(s.size());
+    for (int i = 0; i < s.size(); ++i)
+        in[i] = static_cast<char>(s.data()[i].unicode());
+    Vector<char> out;
+
+    base64Encode(in, out);
+    
+    return jsString(String(out.data(), out.size()));
+}
+
+JSValue* WindowProtoFuncOpen::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Page* page = frame->page();
+
+    String urlString = valueToStringWithUndefinedOrNullCheck(exec, args[0]);
+    AtomicString frameName = args[1]->isUndefinedOrNull() ? "_blank" : AtomicString(args[1]->toString(exec));
+
+    // Because FrameTree::find() returns true for empty strings, we must check for empty framenames.
+    // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
+    if (!allowPopUp(exec, window) && (frameName.isEmpty() || !frame->tree()->find(frameName)))
+        return jsUndefined();
+
+    // Get the target frame for the special cases of _top and _parent
+    if (frameName == "_top")
+        while (frame->tree()->parent())
               frame = frame->tree()->parent();
-              
-      // In those cases, we can schedule a location change right now and return early
-      if (frameName == "_top" || frameName == "_parent") {
-          String completedURL;
-          Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();
-          if (!urlString.isEmpty() && activeFrame)
-              completedURL = activeFrame->document()->completeURL(urlString);
-
-          const Window* window = Window::retrieveWindow(frame);
-          if (!completedURL.isEmpty() && (!completedURL.startsWith("javascript:", false) || (window && window->isSafeScript(exec)))) {
-              bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-              frame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);
-          }
-          return Window::retrieve(frame);
-      }
-      
-      // In the case of a named frame or a new window, we'll use the createWindow() helper
-      WindowFeatures windowFeatures;
-      String features = valueToStringWithUndefinedOrNullCheck(exec, args[2]);
-      parseWindowFeatures(features, windowFeatures);
-      FloatRect windowRect(windowFeatures.x, windowFeatures.y, windowFeatures.width, windowFeatures.height);
-      adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), windowRect, windowRect);
+    else if (frameName == "_parent")
+        if (frame->tree()->parent())
+            frame = frame->tree()->parent();
+
+    // In those cases, we can schedule a location change right now and return early
+    if (frameName == "_top" || frameName == "_parent") {
+        String completedURL;
+        Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();
+        if (!urlString.isEmpty() && activeFrame)
+            completedURL = activeFrame->document()->completeURL(urlString);
 
-      windowFeatures.x = windowRect.x();
-      windowFeatures.y = windowRect.y();
-      windowFeatures.height = windowRect.height();
-      windowFeatures.width = windowRect.width();
+        const Window* window = Window::retrieveWindow(frame);
+        if (!completedURL.isEmpty() && (!completedURL.startsWith("javascript:", false) || (window && window->isSafeScript(exec)))) {
+            bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
+            frame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);
+        }
+        return Window::retrieve(frame);
+    }
+    
+    // In the case of a named frame or a new window, we'll use the createWindow() helper
+    WindowFeatures windowFeatures;
+    String features = valueToStringWithUndefinedOrNullCheck(exec, args[2]);
+    parseWindowFeatures(features, windowFeatures);
+    FloatRect windowRect(windowFeatures.x, windowFeatures.y, windowFeatures.width, windowFeatures.height);
+    adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), windowRect, windowRect);
 
-      frame = createWindow(exec, frame, urlString, frameName, windowFeatures, 0);
+    windowFeatures.x = windowRect.x();
+    windowFeatures.y = windowRect.y();
+    windowFeatures.height = windowRect.height();
+    windowFeatures.width = windowRect.width();
 
-      if (!frame)
-          return jsUndefined();
+    frame = createWindow(exec, frame, urlString, frameName, windowFeatures, 0);
+
+    if (!frame)
+        return jsUndefined();
+
+    return Window::retrieve(frame); // global object
+}
+
+JSValue* WindowProtoFuncScrollBy::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    FrameView *widget = frame->view();
 
-      return Window::retrieve(frame); // global object
-  }
-  case Window::ScrollBy:
     window->updateLayout();
     if(args.size() >= 2 && widget)
       widget->scrollBy(args[0]->toInt32(exec), args[1]->toInt32(exec));
     return jsUndefined();
-  case Window::Scroll:
-  case Window::ScrollTo:
+}
+
+JSValue* WindowProtoFuncScrollTo::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // Also the implementation for window.scroll()
+
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    FrameView *widget = frame->view();
+
     window->updateLayout();
     if (args.size() >= 2 && widget)
       widget->setContentsPos(args[0]->toInt32(exec), args[1]->toInt32(exec));
     return jsUndefined();
-  case Window::MoveBy:
+}
+
+JSValue* WindowProtoFuncMoveBy::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Page* page = frame->page();
+
     if (args.size() >= 2 && page) {
       FloatRect fr = page->chrome()->windowRect();
       FloatRect update = fr;
@@ -1347,7 +1413,19 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
       page->chrome()->setWindowRect(fr);
     }
     return jsUndefined();
-  case Window::MoveTo:
+}
+
+JSValue* WindowProtoFuncMoveTo::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Page* page = frame->page();
+
     if (args.size() >= 2 && page) {
       FloatRect fr = page->chrome()->windowRect();
       FloatRect sr = screenAvailableRect(page->mainFrame()->view());
@@ -1359,7 +1437,19 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
       page->chrome()->setWindowRect(fr);
     }
     return jsUndefined();
-  case Window::ResizeBy:
+}
+
+JSValue* WindowProtoFuncResizeBy::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Page* page = frame->page();
+
     if (args.size() >= 2 && page) {
       FloatRect fr = page->chrome()->windowRect();
       FloatSize dest = fr.size() + FloatSize(args[0]->toFloat(exec), args[1]->toFloat(exec));
@@ -1368,7 +1458,19 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
       page->chrome()->setWindowRect(fr);
     }
     return jsUndefined();
-  case Window::ResizeTo:
+}
+
+JSValue* WindowProtoFuncResizeTo::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Page* page = frame->page();
+
     if (args.size() >= 2 && page) {
       FloatRect fr = page->chrome()->windowRect();
       FloatSize dest = FloatSize(args[0]->toFloat(exec), args[1]->toFloat(exec));
@@ -1377,7 +1479,20 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
       page->chrome()->setWindowRect(fr);
     }
     return jsUndefined();
-  case Window::SetTimeout:
+}
+
+JSValue* WindowProtoFuncSetTimeout::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    JSValue *v = args[0];
+    UString s = v->toString(exec);
+
     if (!window->isSafeScript(exec))
         return jsUndefined();
     if (v->isString()) {
@@ -1397,7 +1512,39 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
     }
     else
       return jsUndefined();
-  case Window::SetInterval:
+}
+
+JSValue* WindowProtoFuncClearTimeout::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    // Also the implementation for window.clearInterval()
+
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    JSValue *v = args[0];
+
+    if (!window->isSafeScript(exec))
+        return jsUndefined();
+    (const_cast<Window*>(window))->clearTimeout(v->toInt32(exec));
+    return jsUndefined();
+}
+
+JSValue* WindowProtoFuncSetInterval::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    JSValue *v = args[0];
+    UString s = v->toString(exec);
+
     if (!window->isSafeScript(exec))
         return jsUndefined();
     if (args.size() >= 2 && v->isString()) {
@@ -1417,39 +1564,69 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
     }
     else
       return jsUndefined();
-  case Window::ClearTimeout:
-  case Window::ClearInterval:
+
+}
+
+JSValue* WindowProtoFuncAddEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
     if (!window->isSafeScript(exec))
         return jsUndefined();
-    (const_cast<Window*>(window))->clearTimeout(v->toInt32(exec));
+    if (JSEventListener* listener = window->findOrCreateJSEventListener(args[1]))
+        if (Document *doc = frame->document())
+            doc->addWindowEventListener(AtomicString(args[0]->toString(exec)), listener, args[2]->toBoolean(exec));
     return jsUndefined();
-  case Window::CaptureEvents:
-  case Window::ReleaseEvents:
-    // If anyone implements these, they need the safe script security check.
+}
+
+JSValue* WindowProtoFuncRemoveEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
     if (!window->isSafeScript(exec))
         return jsUndefined();
-    // Not implemented.
+    if (JSEventListener* listener = window->findJSEventListener(args[1]))
+        if (Document *doc = frame->document())
+            doc->removeWindowEventListener(AtomicString(args[0]->toString(exec)), listener, args[2]->toBoolean(exec));
     return jsUndefined();
-  case Window::AddEventListener:
-        if (!window->isSafeScript(exec))
-            return jsUndefined();
-        if (JSEventListener* listener = window->findOrCreateJSEventListener(args[1]))
-            if (Document *doc = frame->document())
-                doc->addWindowEventListener(AtomicString(args[0]->toString(exec)), listener, args[2]->toBoolean(exec));
+}
+
+JSValue* WindowProtoFuncShowModalDialog::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
         return jsUndefined();
-  case Window::RemoveEventListener:
-        if (!window->isSafeScript(exec))
-            return jsUndefined();
-        if (JSEventListener* listener = window->findJSEventListener(args[1]))
-            if (Document *doc = frame->document())
-                doc->removeWindowEventListener(AtomicString(args[0]->toString(exec)), listener, args[2]->toBoolean(exec));
+
+    return showModalDialog(exec, window, args);
+}
+
+JSValue* WindowProtoFuncNotImplemented::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Window::info))
+        return throwError(exec, TypeError);
+    Window* window = static_cast<Window*>(thisObj);
+    Frame* frame = window->impl()->frame();
+    if (!frame)
         return jsUndefined();
-  case Window::ShowModalDialog: {
-    JSValue* result = showModalDialog(exec, window, args);
-    return result;
-  }
-  }
-  return jsUndefined();
+
+    // If anyone implements these, they need the safe script security check.
+    if (!window->isSafeScript(exec))
+        return jsUndefined();
+    // Not implemented.
+    return jsUndefined();
 }
 
 void Window::updateLayout() const
@@ -1684,21 +1861,21 @@ Window::UnprotectedListenersMap& Window::jsUnprotectedHTMLEventListeners()
 const ClassInfo Location::info = { "Location", 0, &LocationTable };
 /*
 @begin LocationTable 12
-  assign        Location::Assign        DontDelete|Function 1
-  hash          Location::Hash          DontDelete
-  host          Location::Host          DontDelete
-  hostname      Location::Hostname      DontDelete
-  href          Location::Href          DontDelete
-  pathname      Location::Pathname      DontDelete
-  port          Location::Port          DontDelete
-  protocol      Location::Protocol      DontDelete
-  search        Location::Search        DontDelete
-  toString      Location::ToString      DontEnum|DontDelete|Function 0
-  replace       Location::Replace       DontDelete|Function 1
-  reload        Location::Reload        DontDelete|Function 0
+  assign        &LocationProtoFuncAssign::create        DontDelete|Function 1
+  hash          Location::Hash                          DontDelete
+  host          Location::Host                          DontDelete
+  hostname      Location::Hostname                      DontDelete
+  href          Location::Href                          DontDelete
+  pathname      Location::Pathname                      DontDelete
+  port          Location::Port                          DontDelete
+  protocol      Location::Protocol                      DontDelete
+  search        Location::Search                        DontDelete
+  toString      &LocationProtoFuncToString::create      DontEnum|DontDelete|Function 0
+  replace       &LocationProtoFuncReplace::create       DontDelete|Function 1
+  reload        &LocationProtoFuncReload::create        DontDelete|Function 0
 @end
 */
-KJS_IMPLEMENT_PROTOTYPE_FUNCTION(LocationFunc)
+
 Location::Location(Frame *p) : m_frame(p)
 {
 }
@@ -1746,13 +1923,16 @@ bool Location::getOwnPropertySlot(ExecState *exec, const Identifier& propertyNam
   const Window* window = Window::retrieveWindow(m_frame);
   
   const HashEntry *entry = Lookup::findEntry(&LocationTable, propertyName);
-  if (!entry || (entry->value != Replace && entry->value != Reload && entry->value != Assign))
+  if (!entry || !(entry->attr & KJS::Function) || (entry->value.functionValue != &LocationProtoFuncReplace::create
+                                                   && entry->value.functionValue != &LocationProtoFuncReload::create
+                                                   && entry->value.functionValue != &LocationProtoFuncAssign::create))  {
     if (!window || !window->isSafeScript(exec)) {
       slot.setUndefined(this);
       return true;
     }
+  }
 
-  return getStaticPropertySlot<LocationFunc, Location, JSObject>(exec, &LocationTable, this, propertyName, slot);
+  return getStaticPropertySlot<Location, JSObject>(exec, &LocationTable, this, propertyName, slot);
 }
 
 void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr)
@@ -1771,10 +1951,10 @@ void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr)
       // cross-domain access to the location is allowed when assigning the whole location,
       // but not when assigning the individual pieces, since that might inadvertently
       // disclose other parts of the original location.
-      if (entry->value != Href && !sameDomainAccess)
+      if (entry->value.intValue != Href && !sameDomainAccess)
           return;
 
-      switch (entry->value) {
+      switch (entry->value.intValue) {
       case Href: {
           Frame* frame = Window::retrieveActive(exec)->impl()->frame();
           if (frame)
@@ -1830,65 +2010,94 @@ void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr)
   }
 }
 
-JSValue *LocationFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
+JSValue* LocationProtoFuncReplace::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
-  if (!thisObj->inherits(&Location::info))
-    return throwError(exec, TypeError);
-  Location *location = static_cast<Location *>(thisObj);
-  Frame *frame = location->frame();
-  if (frame) {
-      
-    Window* window = Window::retrieveWindow(frame);
-    if (id != Location::Replace && !window->isSafeScript(exec))
+    if (!thisObj->inherits(&Location::info))
+        return throwError(exec, TypeError);
+    Location* location = static_cast<Location*>(thisObj);
+    Frame* frame = location->frame();
+    if (!frame)
         return jsUndefined();
-      
-    switch (id) {
-    case Location::Replace:
-    {
-      DeprecatedString str = args[0]->toString(exec);
-      Frame* p = Window::retrieveActive(exec)->impl()->frame();
-      if ( p ) {
-        const Window* window = Window::retrieveWindow(frame);
-        if (!str.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
-          bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-          frame->loader()->scheduleLocationChange(p->loader()->completeURL(str).url(), p->loader()->outgoingReferrer(), true, userGesture);
-        }
-      }
-      break;
-    }
-    case Location::Reload:
-    {
+
+    DeprecatedString str = args[0]->toString(exec);
+    Frame* p = Window::retrieveActive(exec)->impl()->frame();
+    if ( p ) {
       const Window* window = Window::retrieveWindow(frame);
-      if (!frame->loader()->url().url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
+      if (!str.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
         bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-        frame->loader()->scheduleRefresh(userGesture);
+        frame->loader()->scheduleLocationChange(p->loader()->completeURL(str).url(), p->loader()->outgoingReferrer(), true, userGesture);
       }
-      break;
     }
-    case Location::Assign:
-    {
-        Frame *p = Window::retrieveActive(exec)->impl()->frame();
-        if (p) {
-            const Window *window = Window::retrieveWindow(frame);
-            DeprecatedString dstUrl = p->loader()->completeURL(DeprecatedString(args[0]->toString(exec))).url();
-            if (!dstUrl.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
-                bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-                // We want a new history item if this JS was called via a user gesture
-                frame->loader()->scheduleLocationChange(dstUrl, p->loader()->outgoingReferrer(), false, userGesture);
-            }
-        }
-        break;
+
+    return jsUndefined();
+}
+
+JSValue* LocationProtoFuncReload::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Location::info))
+        return throwError(exec, TypeError);
+    Location* location = static_cast<Location*>(thisObj);
+    Frame* frame = location->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Window* window = Window::retrieveWindow(frame);
+    if (!window->isSafeScript(exec))
+        return jsUndefined();
+
+    if (!frame->loader()->url().url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
+      bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
+      frame->loader()->scheduleRefresh(userGesture);
     }
-    case Location::ToString:
-        if (!frame || !Window::retrieveWindow(frame)->isSafeScript(exec))
-            return jsString();
+    return jsUndefined();
+}
 
-        if (!frame->loader()->url().hasPath())
-            return jsString(frame->loader()->url().prettyURL() + "/");
-        return jsString(frame->loader()->url().prettyURL());
+JSValue* LocationProtoFuncAssign::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Location::info))
+        return throwError(exec, TypeError);
+    Location* location = static_cast<Location*>(thisObj);
+    Frame* frame = location->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Window* window = Window::retrieveWindow(frame);
+    if (!window->isSafeScript(exec))
+        return jsUndefined();
+
+    Frame *p = Window::retrieveActive(exec)->impl()->frame();
+    if (p) {
+        const Window *window = Window::retrieveWindow(frame);
+        DeprecatedString dstUrl = p->loader()->completeURL(DeprecatedString(args[0]->toString(exec))).url();
+        if (!dstUrl.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
+            bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
+            // We want a new history item if this JS was called via a user gesture
+            frame->loader()->scheduleLocationChange(dstUrl, p->loader()->outgoingReferrer(), false, userGesture);
+        }
     }
-  }
-  return jsUndefined();
+
+    return jsUndefined();
+}
+
+JSValue* LocationProtoFuncToString::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&Location::info))
+        return throwError(exec, TypeError);
+    Location* location = static_cast<Location*>(thisObj);
+    Frame* frame = location->frame();
+    if (!frame)
+        return jsUndefined();
+
+    Window* window = Window::retrieveWindow(frame);
+    if (!window->isSafeScript(exec))
+        return jsUndefined();
+
+    if (!frame || !Window::retrieveWindow(frame)->isSafeScript(exec))
+        return jsString();
+
+    if (!frame->loader()->url().hasPath())
+        return jsString(frame->loader()->url().prettyURL() + "/");
+    return jsString(frame->loader()->url().prettyURL());
 }
 
 /////////////////////////////////////////////////////////////////////////////
index d47c51bd570166401e54ab8aaa7d3964d70da3e3..d705b2622d9e362f4274c0f2c4d954a135c6570c 100644 (file)
@@ -68,7 +68,6 @@ namespace KJS {
   // This is the only WebCore JS binding which does not inherit from DOMObject
   class Window : public JSGlobalObject {
     friend class Location;
-    friend class WindowFunc;
     friend class ScheduledAction;
   protected:
     Window(WebCore::DOMWindow*);
@@ -143,13 +142,6 @@ namespace KJS {
     static const ClassInfo info;
 
     enum {
-        // Functions
-        AToB, BToA, Open, SetTimeout,
-        ClearTimeout, SetInterval, ClearInterval, CaptureEvents, 
-        ReleaseEvents, AddEventListener, RemoveEventListener, Scroll,
-        ScrollBy, ScrollTo, MoveBy, MoveTo,
-        ResizeBy, ResizeTo, ShowModalDialog,
-
         // Attributes
         Crypto, Event_, Location_, Navigator_,
         ClientInformation,
@@ -168,6 +160,8 @@ namespace KJS {
         XSLTProcessor_
     };
 
+    void updateLayout() const;
+
   private:
     JSValue* getListener(ExecState*, const WebCore::AtomicString& eventType) const;
     void setListener(ExecState*, const WebCore::AtomicString& eventType, JSValue* func);
@@ -177,8 +171,6 @@ namespace KJS {
     static JSValue *indexGetter(ExecState *exec, JSObject *, const Identifier&, const PropertySlot& slot);
     static JSValue *namedItemGetter(ExecState *exec, JSObject *, const Identifier&, const PropertySlot& slot);
 
-    void updateLayout() const;
-
     void clearHelperObjectProperties();
     void clearAllTimeouts();
     int installTimeout(ScheduledAction*, int interval, bool singleShot);
@@ -187,7 +179,27 @@ namespace KJS {
     OwnPtr<WindowPrivate> d;
   };
 
-  KJS_IMPLEMENT_PROTOTYPE_FUNCTION(WindowFunc)
+#define FOR_EACH_CLASS(macro) \
+    macro(WindowProtoFuncAToB) \
+    macro(WindowProtoFuncBToA) \
+    macro(WindowProtoFuncOpen) \
+    macro(WindowProtoFuncScrollBy) \
+    macro(WindowProtoFuncScrollTo) \
+    macro(WindowProtoFuncMoveBy) \
+    macro(WindowProtoFuncMoveTo) \
+    macro(WindowProtoFuncResizeBy) \
+    macro(WindowProtoFuncResizeTo) \
+    macro(WindowProtoFuncSetTimeout) \
+    macro(WindowProtoFuncClearTimeout) \
+    macro(WindowProtoFuncSetInterval) \
+    macro(WindowProtoFuncAddEventListener) \
+    macro(WindowProtoFuncRemoveEventListener) \
+    macro(WindowProtoFuncShowModalDialog) \
+    macro(WindowProtoFuncNotImplemented) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
 
   /**
    * An action (either function or string) to be executed after a specified
@@ -223,7 +235,16 @@ namespace KJS {
     WebCore::Frame* m_frame;
   };
 
-} // namespace
+#define FOR_EACH_CLASS(macro) \
+    macro(LocationProtoFuncAssign) \
+    macro(LocationProtoFuncToString) \
+    macro(LocationProtoFuncReplace) \
+    macro(LocationProtoFuncReload) \
+
+FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)
+#undef FOR_EACH_CLASS
+
+} // namespace KJS
 
 namespace WebCore {
     KJS::JSValue* toJS(KJS::ExecState*, DOMWindow*);
index dd4af6ce56fb412861eecb604764857320af3ed6..0a4b03661a0e63f26846831bf89c216dfa2deb7f 100644 (file)
@@ -389,8 +389,8 @@ sub GenerateHeader
     my $numCustomAttributes = 0;
 
     # Attribute and function enums
-    my $hasAttrFunctionEnum = ($numAttributes + $numFunctions > 0) || $dataNode->extendedAttributes->{"GenerateConstructor"};
-    push(@headerContent, "    enum {\n") if ($hasAttrFunctionEnum);
+    my $hasAttrEnum = ($numAttributes > 0) || $dataNode->extendedAttributes->{"GenerateConstructor"};
+    push(@headerContent, "    enum {\n") if ($hasAttrEnum);
 
     if ($numAttributes > 0) {
         push(@headerContent, "        // Attributes\n        ");
@@ -419,29 +419,10 @@ sub GenerateHeader
     if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
         push(@headerContent, "\n\n") if $numAttributes > 0;
         push(@headerContent, "        // The Constructor Attribute\n");
-        push(@headerContent, "        ConstructorAttrNum" . ($numFunctions ? ", " : ""));
+        push(@headerContent, "        ConstructorAttrNum");
     }
 
-    if ($numFunctions > 0) {
-        push(@headerContent, "\n\n") if $numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"};
-        push(@headerContent,"        // Functions\n        ");
-
-        $i = -1;
-        foreach my $function (@{$dataNode->functions}) {
-            $i++;
-
-            push(@headerContent, "\n        ") if ((($i % 4) eq 0) and ($i ne 0));
-
-            $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"};
-
-            my $value = WK_ucfirst($function->signature->name) . "FuncNum";
-            $value .= ", " if ($i < $numFunctions - 1);
-            push(@headerContent, $value);
-        }
-    }
-
-
-    push(@headerContent, "\n    };\n") if ($hasAttrFunctionEnum);
+    push(@headerContent, "\n    };\n") if ($hasAttrEnum);
 
     if ($numCustomAttributes > 0) {
         push(@headerContent, "\n    // Custom attributes\n");
@@ -462,6 +443,10 @@ sub GenerateHeader
         }
     }
 
+    foreach my $function (@{$dataNode->functions}) {
+        $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"};
+    }
+
     if ($numCustomFunctions > 0) {
         push(@headerContent, "\n    // Custom functions\n");
         foreach my $function (@{$dataNode->functions}) {
@@ -562,7 +547,10 @@ sub GenerateHeader
     push(@headerContent, "};\n\n");
 
     if ($numFunctions > 0) {
-        push(@headerContent, prototypeFunctionFor($className));
+        push(@headerContent,"// Functions\n\n");
+        foreach my $function (@{$dataNode->functions}) {
+            push(@headerContent, prototypeFunctionFor($className, WK_ucfirst($function->signature->name)));
+        }        
     }
 
     push(@headerContent, "} // namespace WebCore\n\n");
@@ -724,7 +712,7 @@ sub GenerateImplementation
         my $name = $function->signature->name;
         push(@hashKeys, $name);
 
-        my $value = $className . "::" . WK_ucfirst($name) . "FuncNum";
+        my $value = "&" . $className . "PrototypeFunction" . WK_ucfirst($name) . "::create";
         push(@hashValues, $value);
 
         my @specials = ();
@@ -758,11 +746,11 @@ sub GenerateImplementation
         push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
         push(@implContent, "{\n");
         if ($numConstants eq 0) {
-            push(@implContent, "    return getStaticFunctionSlot<${className}PrototypeFunction, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
+            push(@implContent, "    return getStaticFunctionSlot<JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
         } elsif ($numFunctions eq 0) {
             push(@implContent, "    return getStaticValueSlot<${className}Prototype, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
         } else {
-            push(@implContent, "    return getStaticPropertySlot<${className}PrototypeFunction, ${className}Prototype, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
+            push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, &${className}PrototypeTable, this, propertyName, slot);\n");
         }
         push(@implContent, "}\n\n");
     }
@@ -1089,107 +1077,99 @@ sub GenerateImplementation
     }
 
     # Functions
-    if ($numFunctions ne 0) {
-        push(@implContent, "JSValue* ${className}PrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)\n{\n");
-        push(@implContent, "    if (!thisObj->inherits(&${className}::info))\n");
-        push(@implContent, "      return throwError(exec, TypeError);\n\n");
-
-        push(@implContent, "    $className* castedThisObj = static_cast<$className*>(thisObj);\n");
-        if ($podType) {
-            push(@implContent, "    JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n");
-            push(@implContent, "    $podType imp(*wrapper);\n\n");
-        } else {
-            push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n\n");
-        }
-
-        push(@implContent, "    switch (id) {\n");
-
-        my $hasCustomFunctionsOnly = 1;
-
+    if ($numFunctions > 0) {
         foreach my $function (@{$dataNode->functions}) {
-            push(@implContent, "    case ${className}::" . WK_ucfirst($function->signature->name) . "FuncNum: {\n");
-
-            if ($function->signature->extendedAttributes->{"Custom"}) {
-                push(@implContent, "        return castedThisObj->" . $function->signature->name . "(exec, args);\n    }\n");
-                next;
-            }
+            my $functionClassName = $className . "PrototypeFunction" . WK_ucfirst($function->signature->name);
+            push(@implContent, "JSValue* ${functionClassName}::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)\n");
+            push(@implContent, "{\n");
+            push(@implContent, "    if (!thisObj->inherits(&${className}::info))\n");
+            push(@implContent, "      return throwError(exec, TypeError);\n\n");
 
-            $hasCustomFunctionsOnly = 0;
             AddIncludesForType($function->signature->type);
 
-            if (@{$function->raisesExceptions}) {
-                push(@implContent, "        ExceptionCode ec = 0;\n");
-            }
-
-            if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
-                push(@implContent, "        if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
-                push(@implContent, "            return jsUndefined();\n");
-                $implIncludes{"kjs_dom.h"} = 1;
-            }
+            push(@implContent, "    $className* castedThisObj = static_cast<$className*>(thisObj);\n");
 
-            my $paramIndex = 0;
-            my $functionString = "imp" . ($podType ? "." : "->") . $function->signature->name . "(";
+            if ($function->signature->extendedAttributes->{"Custom"}) {
+                push(@implContent, "        return castedThisObj->" . $function->signature->name . "(exec, args);\n");
+            } else {
+                if ($podType) {
+                    push(@implContent, "    JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n");
+                    push(@implContent, "    $podType imp(*wrapper);\n\n");
+                } else {
+                    push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n\n");
+                }
 
-            my $numParameters = @{$function->parameters};
-            my $hasOptionalArguments = 0;
 
-            foreach my $parameter (@{$function->parameters}) {
-                if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
-                    push(@implContent, "\n        int argsCount = args.size();\n");
-                    $hasOptionalArguments = 1;
+                if (@{$function->raisesExceptions}) {
+                    push(@implContent, "    ExceptionCode ec = 0;\n");
                 }
 
-                if ($hasOptionalArguments) {
-                    push(@implContent, "        if (argsCount < " . ($paramIndex + 1) . ") {\n");
-                    GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 3, $podType, $implClassName);
-                    push(@implContent, "        }\n\n");
+                if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
+                    push(@implContent, "    if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
+                    push(@implContent, "        return jsUndefined();\n");
+                    $implIncludes{"kjs_dom.h"} = 1;
                 }
 
-                my $name = $parameter->name;
-                
-                if ($parameter->type eq "XPathNSResolver") {
-                    push(@implContent, "        RefPtr<XPathNSResolver> customResolver;\n");
-                    push(@implContent, "        XPathNSResolver* resolver = toXPathNSResolver(args[$paramIndex]);\n");
-                    push(@implContent, "        if (!resolver) {\n");
-                    push(@implContent, "            customResolver = JSCustomXPathNSResolver::create(exec, args[$paramIndex]);\n");
-                    push(@implContent, "            if (exec->hadException())\n");
-                    push(@implContent, "                return jsUndefined();\n");
-                    push(@implContent, "            resolver = customResolver.get();\n");
-                    push(@implContent, "        }\n");
-                } else {
-                    push(@implContent, "        bool ${name}Ok;\n") if TypeCanFailConversion($parameter);
-                    push(@implContent, "        " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args[$paramIndex]", TypeCanFailConversion($parameter) ? "${name}Ok" : undef) . ";\n");
-                    if (TypeCanFailConversion($parameter)) {
-                        push(@implContent, "        if (!${name}Ok) {\n");
-                        push(@implContent, "            setDOMException(exec, TYPE_MISMATCH_ERR);\n");
-                        push(@implContent, "            return jsUndefined();\n        }\n");
+                my $paramIndex = 0;
+                my $functionString = "imp" . ($podType ? "." : "->") . $function->signature->name . "(";
+
+                my $numParameters = @{$function->parameters};
+                my $hasOptionalArguments = 0;
+
+                foreach my $parameter (@{$function->parameters}) {
+                    if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
+                        push(@implContent, "\n    int argsCount = args.size();\n");
+                        $hasOptionalArguments = 1;
                     }
 
-                    # If a parameter is "an index", it should throw an INDEX_SIZE_ERR
-                    # exception
-                    if ($parameter->extendedAttributes->{"IsIndex"}) {
-                        $implIncludes{"ExceptionCode.h"} = 1;
-                        push(@implContent, "        if ($name < 0) {\n");
-                        push(@implContent, "            setDOMException(exec, INDEX_SIZE_ERR);\n");
-                        push(@implContent, "            return jsUndefined();\n        }\n");
+                    if ($hasOptionalArguments) {
+                        push(@implContent, "    if (argsCount < " . ($paramIndex + 1) . ") {\n");
+                        GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $podType, $implClassName);
+                        push(@implContent, "    }\n\n");
                     }
-                }
 
-                $functionString .= ", " if $paramIndex;
-                $functionString .= $name;
+                    my $name = $parameter->name;
+                    
+                    if ($parameter->type eq "XPathNSResolver") {
+                        push(@implContent, "    RefPtr<XPathNSResolver> customResolver;\n");
+                        push(@implContent, "    XPathNSResolver* resolver = toXPathNSResolver(args[$paramIndex]);\n");
+                        push(@implContent, "    if (!resolver) {\n");
+                        push(@implContent, "        customResolver = JSCustomXPathNSResolver::create(exec, args[$paramIndex]);\n");
+                        push(@implContent, "        if (exec->hadException())\n");
+                        push(@implContent, "            return jsUndefined();\n");
+                        push(@implContent, "        resolver = customResolver.get();\n");
+                        push(@implContent, "    }\n");
+                    } else {
+                        push(@implContent, "    bool ${name}Ok;\n") if TypeCanFailConversion($parameter);
+                        push(@implContent, "    " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args[$paramIndex]", TypeCanFailConversion($parameter) ? "${name}Ok" : undef) . ";\n");
+                        if (TypeCanFailConversion($parameter)) {
+                            push(@implContent, "    if (!${name}Ok) {\n");
+                            push(@implContent, "        setDOMException(exec, TYPE_MISMATCH_ERR);\n");
+                            push(@implContent, "        return jsUndefined();\n        }\n");
+                        }
+
+                        # If a parameter is "an index", it should throw an INDEX_SIZE_ERR
+                        # exception
+                        if ($parameter->extendedAttributes->{"IsIndex"}) {
+                            $implIncludes{"ExceptionCode.h"} = 1;
+                            push(@implContent, "    if ($name < 0) {\n");
+                            push(@implContent, "        setDOMException(exec, INDEX_SIZE_ERR);\n");
+                            push(@implContent, "        return jsUndefined();\n");
+                            push(@implContent, "    }\n");
+                        }
+                    }
 
-                $paramIndex++;
-            }
+                    $functionString .= ", " if $paramIndex;
+                    $functionString .= $name;
 
-            push(@implContent, "\n");
-            GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $podType, $implClassName);
+                    $paramIndex++;
+                }
 
-            push(@implContent, "    }\n"); # end case
+                push(@implContent, "\n");
+                GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $podType, $implClassName);
+            }
+            push(@implContent, "}\n\n");
         }
-        push(@implContent, "    }\n"); # end switch
-        push(@implContent, "    (void)imp;\n") if $hasCustomFunctionsOnly;
-        push(@implContent, "    return 0;\n");
-        push(@implContent, "}\n");
     }
 
     if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
@@ -1642,7 +1622,7 @@ sub GenerateHashTable
             my $key = @$keys[$entry];
 
             push(@implContent, "    \{ \"" . $key . "\"");
-            push(@implContent, ", " . @$values[$entry]);
+            push(@implContent, ", \{ (intptr_t)" . @$values[$entry] . " \}");
             push(@implContent, ", " . @$specials[$entry]);
             push(@implContent, ", " . @$parameters[$entry]);
             push(@implContent, ", ");
@@ -1653,7 +1633,7 @@ sub GenerateHashTable
                 push(@implContent, "0 \}");
             }
         } else {
-            push(@implContent, "    { 0, 0, 0, 0, 0 }");
+            push(@implContent, "    { 0, { 0 }, 0, 0, 0 }");
         }
 
         push(@implContent, ",") unless($i eq $size - 1);
@@ -1809,21 +1789,24 @@ EOF
 
 sub prototypeFunctionFor
 {
-    my $className = shift;
+    my ($className, $functionName) = @_;
+    my $name = $className . "PrototypeFunction" . $functionName;
 
 my $implContent = << "EOF";
-class ${className}PrototypeFunction : public KJS::InternalFunctionImp {
-public:
-    ${className}PrototypeFunction(KJS::ExecState* exec, int i, int len, const KJS::Identifier& name)
+class ${name} : public KJS::InternalFunctionImp {
+public: \
+    static KJS::InternalFunctionImp* create(KJS::ExecState* exec, int len, const KJS::Identifier& name)
+    {
+        return new ${name}(exec, len, name);
+    }
+
+    ${name}(KJS::ExecState* exec, int len, const KJS::Identifier& name)
         : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
-        , id(i)
     {
-        put(exec, exec->propertyNames().length, KJS::jsNumber(len), KJS::DontDelete|KJS::ReadOnly|KJS::DontEnum);
+        put(exec, exec->propertyNames().length, KJS::jsNumber(len), KJS::DontDelete | KJS::ReadOnly | KJS::DontEnum);
     }
-    virtual KJS::JSValue* callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&);
 
-private:
-    int id;
+    virtual KJS::JSValue* callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&);
 };
 
 EOF