Changeset 53666 in webkit
- Timestamp:
- Jan 21, 2010 6:23:34 PM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 1 added
- 1 deleted
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r53665 r53666 1 2010-01-21 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 Reviewed by Sam Weinig. 4 5 SVG JS bindings "context" pointer needs to move onto binding impls 6 https://bugs.webkit.org/show_bug.cgi?id=27243 7 8 Rewrite SVG DOM JSC bindings to use a global DOMObject <-> SVGElement context map, similar to V8's approach. 9 This allows us to remove DOMObjectWithSVGContext and make all SVG JS objects use DOMObjectWithGlobalPointer. 10 We're fitting again in JS_CELL_SIZE, and there's no need to special case SVG anymore. 11 12 Not adding a new test, as we have yet to identify how to test that we're passing around correct global objects. 13 For now this is just a code cleanup which lets me continue making progress in that area of the code. 14 15 * GNUmakefile.am: Add new DOMObjectWithSVGContext.h to build. 16 * WebCore.gypi: Ditto. 17 * WebCore.vcproj/WebCore.vcproj: Ditto. 18 * WebCore.xcodeproj/project.pbxproj: Ditto. 19 * bindings/js/DOMObjectWithSVGContext.h: Removed. 20 * bindings/js/JSDOMBinding.cpp: 21 (WebCore::setDOMException): Add comment, that passing 0 context is intentional. 22 * bindings/js/JSDOMBinding.h: 23 (WebCore::createDOMObjectWrapper): Add to JSSVGContextCache, when creating wrappers. 24 (WebCore::getDOMObjectWrapper): Add assertion guarding the JSSVGContextCache is in-sync with the passed context. 25 * bindings/js/JSSVGContextCache.h: Added. Maps DOMObjects to SVGElements - just like V8 approachs to this problem. 26 (WebCore::JSSVGContextCache::wrapperMap): 27 (WebCore::JSSVGContextCache::addWrapper): 28 (WebCore::JSSVGContextCache::forgetWrapper): 29 (WebCore::JSSVGContextCache::propagateSVGDOMChange): 30 (WebCore::JSSVGContextCache::svgContextForDOMObject): 31 * bindings/js/JSSVGLengthCustom.cpp: Retrieve context from cache, instead of taking it from the JS* class. 32 (WebCore::JSSVGLength::value): 33 (WebCore::JSSVGLength::convertToSpecifiedUnits): 34 * bindings/js/JSSVGMatrixCustom.cpp Ditto.: 35 (WebCore::JSSVGMatrix::multiply): 36 (WebCore::JSSVGMatrix::inverse): 37 (WebCore::JSSVGMatrix::rotateFromVector): 38 * bindings/js/JSSVGPODListCustom.h: Ditto. 39 (WebCore::JSSVGPODListCustom::finishGetter): 40 (WebCore::JSSVGPODListCustom::finishSetter): 41 (WebCore::JSSVGPODListCustom::finishSetterReadOnlyResult): 42 (WebCore::JSSVGPODListCustom::clear): 43 (WebCore::JSSVGPODListCustom::initialize): 44 * bindings/js/JSSVGPODTypeWrapper.h: Ditto. 45 (WebCore::JSSVGDynamicPODTypeWrapper::commitChange): 46 (WebCore::JSSVGStaticPODTypeWrapper::commitChange): 47 (WebCore::JSSVGStaticPODTypeWrapperWithPODTypeParent::commitChange): 48 (WebCore::JSSVGStaticPODTypeWrapperWithParent::commitChange): 49 (WebCore::JSSVGPODTypeWrapperCreatorForList::create): 50 (WebCore::JSSVGPODTypeWrapperCreatorForList::commitChange): 51 * bindings/js/JSSVGPathSegCustom.cpp: Ditto. 52 (WebCore::toJS): 53 * bindings/js/JSSVGPathSegListCustom.cpp: Ditto. 54 (WebCore::JSSVGPathSegList::clear): 55 (WebCore::JSSVGPathSegList::initialize): 56 (WebCore::JSSVGPathSegList::getItem): 57 (WebCore::JSSVGPathSegList::insertItemBefore): 58 (WebCore::JSSVGPathSegList::replaceItem): 59 (WebCore::JSSVGPathSegList::removeItem): 60 (WebCore::JSSVGPathSegList::appendItem): 61 * bindings/scripts/CodeGeneratorJS.pm: 62 * svg/SVGAngle.h: Remove unneeded associatedAttributeName() method. 63 * svg/SVGPreserveAspectRatio.h: Ditto. 64 * svg/SVGTransform.h: Ditto. 65 1 66 2010-01-21 Kevin Ollivier <kevino@theolliviers.com> 2 67 -
trunk/WebCore/GNUmakefile.am
r53644 r53666 2932 2932 2933 2933 webcore_sources += \ 2934 WebCore/bindings/js/JSSVGContextCache.h \ 2934 2935 WebCore/bindings/js/JSSVGElementInstanceCustom.cpp \ 2935 2936 WebCore/bindings/js/JSSVGLengthCustom.cpp \ -
trunk/WebCore/WebCore.gypi
r53649 r53666 586 586 'bindings/js/JSStyleSheetCustom.cpp', 587 587 'bindings/js/JSStyleSheetListCustom.cpp', 588 'bindings/js/JSSVGContextCache.h', 588 589 'bindings/js/JSSVGElementInstanceCustom.cpp', 589 590 'bindings/js/JSSVGLengthCustom.cpp', -
trunk/WebCore/WebCore.vcproj/WebCore.vcproj
r53644 r53666 38961 38961 </File> 38962 38962 <File 38963 RelativePath="..\bindings\js\JSSVGContextCache.h" 38964 > 38965 </File> 38966 <File 38963 38967 RelativePath="..\bindings\js\JSSVGElementInstanceCustom.cpp" 38964 38968 > -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r53644 r53666 63 63 082341C50FCF3A9500D75BD6 /* WMLSelectElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 082341C30FCF3A9400D75BD6 /* WMLSelectElement.cpp */; }; 64 64 082341C60FCF3A9500D75BD6 /* WMLSelectElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 082341C40FCF3A9400D75BD6 /* WMLSelectElement.h */; }; 65 082FCAC4110927CE00CC4821 /* JSSVGContextCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 082FCAC3110927CE00CC4821 /* JSSVGContextCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; 65 66 08385FF610F0186000BFE07B /* SVGMarkerData.h in Headers */ = {isa = PBXBuildFile; fileRef = 08385FF510F0186000BFE07B /* SVGMarkerData.h */; }; 66 67 0839476C0ECE4BD600027350 /* WMLElementFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08FB84B00ECE373300DC064E /* WMLElementFactory.cpp */; }; … … 5327 5328 082341C30FCF3A9400D75BD6 /* WMLSelectElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLSelectElement.cpp; sourceTree = "<group>"; }; 5328 5329 082341C40FCF3A9400D75BD6 /* WMLSelectElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLSelectElement.h; sourceTree = "<group>"; }; 5330 082FCAC3110927CE00CC4821 /* JSSVGContextCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSVGContextCache.h; sourceTree = "<group>"; }; 5329 5331 08385FF510F0186000BFE07B /* SVGMarkerData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGMarkerData.h; sourceTree = "<group>"; }; 5330 5332 083DAEA20F01A7FB00342754 /* RenderTextControlMultiLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTextControlMultiLine.cpp; sourceTree = "<group>"; }; … … 14763 14765 BC98A27C0C0C9950004BEBF7 /* JSStyleSheetCustom.cpp */, 14764 14766 A84EBD770CB8C89200079609 /* JSStyleSheetListCustom.cpp */, 14767 082FCAC3110927CE00CC4821 /* JSSVGContextCache.h */, 14765 14768 08A48A6D0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp */, 14766 14769 08E4FE450E2BD41400F4CAE0 /* JSSVGLengthCustom.cpp */, … … 18448 18451 59B5977511086579007159E8 /* BridgeJSC.h in Headers */, 18449 18452 93C4F6EB1108F9A50099D0DB /* AccessibilityScrollbar.h in Headers */, 18453 082FCAC4110927CE00CC4821 /* JSSVGContextCache.h in Headers */, 18450 18454 ); 18451 18455 runOnlyForDeploymentPostprocessing = 0; -
trunk/WebCore/bindings/js/JSDOMBinding.cpp
r53514 r53666 731 731 #if ENABLE(SVG) 732 732 case SVGExceptionType: 733 errorObject = toJS(exec, globalObject, SVGException::create(description).get(), 0 );733 errorObject = toJS(exec, globalObject, SVGException::create(description).get(), 0 /* no context on purpose */); 734 734 break; 735 735 #endif -
trunk/WebCore/bindings/js/JSDOMBinding.h
r53514 r53666 24 24 25 25 #include "JSDOMGlobalObject.h" 26 #include "JSSVGContextCache.h" 26 27 #include "Document.h" 27 28 #include <runtime/Completion.h> … … 302 303 template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) 303 304 { 304 ASSERT(object);305 ASSERT( !getCachedDOMObjectWrapper(exec, object));306 WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object, context);307 cacheDOMObjectWrapper(exec, object, wrapper);305 DOMObject* wrapper = createDOMObjectWrapper<WrapperClass, DOMClass>(exec, globalObject, object); 306 ASSERT(wrapper); 307 if (context) 308 JSSVGContextCache::addWrapper(wrapper, context); 308 309 return wrapper; 309 310 } … … 312 313 if (!object) 313 314 return JSC::jsNull(); 314 if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) 315 if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) { 316 ASSERT(JSSVGContextCache::svgContextForDOMObject(wrapper) == context); 315 317 return wrapper; 316 return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object, context); 318 } 319 return createDOMObjectWrapper<WrapperClass, DOMClass>(exec, globalObject, object, context); 317 320 } 318 321 #endif -
trunk/WebCore/bindings/js/JSSVGLengthCustom.cpp
r43122 r53666 29 29 JSValue JSSVGLength::value(ExecState* exec) const 30 30 { 31 SVGLength imp(*impl()); 32 return jsNumber(exec, imp.value(context())); 31 JSSVGPODTypeWrapper<SVGLength>* imp = impl(); 32 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(const_cast<JSSVGLength*>(this)); 33 34 SVGLength podImp(*imp); 35 return jsNumber(exec, podImp.value(context)); 33 36 } 34 37 35 38 JSValue JSSVGLength::convertToSpecifiedUnits(ExecState* exec, const ArgList& args) 36 39 { 37 JSSVGPODTypeWrapper<SVGLength>* wrapper = impl(); 40 JSSVGPODTypeWrapper<SVGLength>* imp = impl(); 41 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 38 42 39 SVGLength imp(*wrapper);40 imp.convertToSpecifiedUnits(args.at(0).toInt32(exec), context());43 SVGLength podImp(*imp); 44 podImp.convertToSpecifiedUnits(args.at(0).toInt32(exec), context); 41 45 42 wrapper->commitChange(imp, context());46 imp->commitChange(podImp, this); 43 47 return jsUndefined(); 44 48 } -
trunk/WebCore/bindings/js/JSSVGMatrixCustom.cpp
r50561 r53666 45 45 TransformationMatrix m2(*(matrixObj->impl())); 46 46 47 JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2)).get(), m_context.get()); 48 49 return result; 47 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 48 return toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2)).get(), context); 50 49 } 51 50 … … 53 52 { 54 53 TransformationMatrix imp(*impl()); 55 JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), m_context.get()); 54 55 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 56 JSValue result = toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), context); 56 57 57 58 if (!imp.isInvertible()) … … 68 69 float y = args.at(1).toFloat(exec); 69 70 70 JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), m_context.get()); 71 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 72 JSValue result = toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), context); 71 73 72 74 if (x == 0.0 || y == 0.0) -
trunk/WebCore/bindings/js/JSSVGPODListCustom.h
r53086 r53666 23 23 #define JSSVGPODListCustom_h 24 24 25 #include "JSSVGContextCache.h" 25 26 #include "JSSVGPODTypeWrapper.h" 26 27 #include "SVGList.h" … … 38 39 }; 39 40 40 template<typename PODType> 41 static JSC::JSValue finishGetter(JSC::ExecState* exec, ExceptionCode& ec, SVGElement* context, 42 typename JSSVGPODListTraits<PODType>::PODList* list, 41 template<typename JSPODListType, typename PODType> 42 static JSC::JSValue finishGetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, 43 PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) 44 { 45 if (ec) { 46 setDOMException(exec, ec); 47 return JSC::jsUndefined(); 48 } 49 50 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 51 52 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper); 53 return toJS(exec, wrapper->globalObject(), 54 JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), listImp->associatedAttributeName()).get(), context); 55 } 56 57 template<typename JSPODListType, typename PODType> 58 static JSC::JSValue finishSetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, 43 59 PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) 44 60 { … … 48 64 } 49 65 50 return toJS(exec, deprecatedGlobalObjectForPrototype(exec), 51 JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), list->associatedAttributeName()).get(), context); 66 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 67 68 const QualifiedName& attributeName = listImp->associatedAttributeName(); 69 JSSVGContextCache::propagateSVGDOMChange(wrapper, attributeName); 70 71 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper); 72 return toJS(exec, wrapper->globalObject(), 73 JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), attributeName).get(), context); 52 74 } 53 75 54 template<typename PODType> 55 static JSC::JSValue finishSetter(JSC::ExecState* exec, ExceptionCode& ec, SVGElement* context, 56 typename JSSVGPODListTraits<PODType>::PODList* list, 57 PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) 76 template<typename JSPODListType, typename PODType> 77 static JSC::JSValue finishSetterReadOnlyResult(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, 78 PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) 58 79 { 59 80 if (ec) { … … 62 83 } 63 84 64 const QualifiedName& attributeName = list->associatedAttributeName(); 65 context->svgAttributeChanged(attributeName); 66 67 return toJS(exec, deprecatedGlobalObjectForPrototype(exec), 68 JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), attributeName).get(), context); 69 } 70 71 template<typename PODType> 72 static JSC::JSValue finishSetterReadOnlyResult(JSC::ExecState* exec, ExceptionCode& ec, SVGElement* context, 73 typename JSSVGPODListTraits<PODType>::PODList* list, 74 PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) 75 { 76 if (ec) { 77 setDOMException(exec, ec); 78 return JSC::jsUndefined(); 79 } 80 context->svgAttributeChanged(list->associatedAttributeName()); 81 return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<PODType>::create(*item).get(), context); 85 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 86 JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName()); 87 return toJS(exec, wrapper->globalObject(), 88 JSSVGStaticPODTypeWrapper<PODType>::create(*item).get(), 0 /* no context on purpose */); 82 89 } 83 90 … … 93 100 setDOMException(exec, ec); 94 101 else 95 wrapper->context()->svgAttributeChanged(listImp->associatedAttributeName());102 JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName()); 96 103 97 104 return JSC::jsUndefined(); … … 104 111 ExceptionCode ec = 0; 105 112 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 106 return finishSetter<PODType>(exec, ec, wrapper->context(), listImp, 107 listImp->initialize(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec)); 108 113 return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, 114 listImp->initialize(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec)); 109 115 } 110 116 … … 122 128 ExceptionCode ec = 0; 123 129 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 124 return finishGetter< PODType>(exec, ec, wrapper->context(), listImp,125 listImp->getItem(index, ec));130 return finishGetter<JSPODListType, PODType>(exec, ec, wrapper, 131 listImp->getItem(index, ec)); 126 132 } 127 133 … … 139 145 ExceptionCode ec = 0; 140 146 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 141 return finishSetter< PODType>(exec, ec, wrapper->context(), listImp,142 listImp->insertItemBefore(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec));147 return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, 148 listImp->insertItemBefore(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec)); 143 149 } 144 150 … … 156 162 ExceptionCode ec = 0; 157 163 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 158 return finishSetter< PODType>(exec, ec, wrapper->context(), listImp,159 listImp->replaceItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec));164 return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, 165 listImp->replaceItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec)); 160 166 } 161 167 … … 173 179 ExceptionCode ec = 0; 174 180 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 175 return finishSetterReadOnlyResult< PODType>(exec, ec, wrapper->context(), listImp,176 listImp->removeItem(index, ec));181 return finishSetterReadOnlyResult<JSPODListType, PODType>(exec, ec, wrapper, 182 listImp->removeItem(index, ec)); 177 183 } 178 184 … … 183 189 ExceptionCode ec = 0; 184 190 typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); 185 return finishSetter< PODType>(exec, ec, wrapper->context(), listImp,186 listImp->appendItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec));191 return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, 192 listImp->appendItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec)); 187 193 } 188 194 -
trunk/WebCore/bindings/js/JSSVGPODTypeWrapper.h
r52082 r53666 29 29 30 30 #if ENABLE(SVG) 31 #include "JSSVGContextCache.h" 31 32 #include "SVGElement.h" 32 33 #include <wtf/StdLibExtras.h> … … 34 35 namespace WebCore { 35 36 37 class DOMObject; 38 36 39 template<typename PODType> 37 40 class JSSVGPODTypeWrapper : public RefCounted<JSSVGPODTypeWrapper<PODType> > { … … 40 43 41 44 virtual operator PODType() = 0; 42 virtual void commitChange(PODType, SVGElement*) = 0;45 virtual void commitChange(PODType, DOMObject*) = 0; 43 46 }; 44 47 … … 87 90 } 88 91 89 virtual void commitChange(PODType type, SVGElement* context)92 virtual void commitChange(PODType type, DOMObject* wrapper) 90 93 { 91 94 (m_creator.get()->*m_setter)(type); 92 93 if (context) 94 context->svgAttributeChanged(m_creator->associatedAttributeName()); 95 JSSVGContextCache::propagateSVGDOMChange(wrapper, m_creator->associatedAttributeName()); 95 96 } 96 97 … … 131 132 } 132 133 133 virtual void commitChange(PODType type, SVGElement*)134 virtual void commitChange(PODType type, DOMObject*) 134 135 { 135 136 m_podType = type; … … 155 156 } 156 157 157 virtual void commitChange(PODType type, SVGElement* context)158 { 159 JSSVGStaticPODTypeWrapper<PODType>::commitChange(type, context);160 m_parentType->commitChange(ParentTypeArg(type), context);158 virtual void commitChange(PODType type, DOMObject* wrapper) 159 { 160 JSSVGStaticPODTypeWrapper<PODType>::commitChange(type, wrapper); 161 m_parentType->commitChange(ParentTypeArg(type), wrapper); 161 162 } 162 163 … … 193 194 } 194 195 195 virtual void commitChange(PODType type, SVGElement*)196 virtual void commitChange(PODType type, DOMObject*) 196 197 { 197 198 (m_parent.get()->*m_setter)(type); … … 238 239 } 239 240 240 virtual void commitChange(PODType type, SVGElement* context)241 virtual void commitChange(PODType type, DOMObject* wrapper) 241 242 { 242 243 if (!m_setter) … … 244 245 245 246 (m_creator.get()->*m_setter)(type); 246 247 if (context) 248 context->svgAttributeChanged(m_associatedAttributeName); 247 JSSVGContextCache::propagateSVGDOMChange(wrapper, m_associatedAttributeName); 249 248 } 250 249 -
trunk/WebCore/bindings/js/JSSVGPathSegCustom.cpp
r51363 r53666 22 22 #if ENABLE(SVG) 23 23 #include "JSSVGPathSeg.h" 24 25 #include "JSDOMBinding.h" 24 26 #include "JSSVGPathSegArcAbs.h" 25 27 #include "JSSVGPathSegArcRel.h" … … 41 43 #include "JSSVGPathSegMovetoAbs.h" 42 44 #include "JSSVGPathSegMovetoRel.h" 43 44 #include "JSDOMBinding.h"45 46 45 #include "SVGPathSeg.h" 47 46 #include "SVGPathSegArc.h" … … 65 64 return jsNull(); 66 65 67 if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) 66 if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) { 67 ASSERT(JSSVGContextCache::svgContextForDOMObject(wrapper) == context); 68 68 return wrapper; 69 } 69 70 70 71 switch (object->pathSegType()) { … … 116 117 117 118 #endif // ENABLE(SVG) 118 119 // vim:ts=4:noet -
trunk/WebCore/bindings/js/JSSVGPathSegListCustom.cpp
r46346 r53666 25 25 #include "Document.h" 26 26 #include "Frame.h" 27 #include "JSSVGContextCache.h" 27 28 #include "JSSVGPathSeg.h" 28 29 #include "SVGDocumentExtensions.h" … … 40 41 ExceptionCode ec = 0; 41 42 42 SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl());43 imp->clear(ec);43 SVGPathSegList* list = impl(); 44 list->clear(ec); 44 45 45 46 setDOMException(exec, ec); 46 47 47 m_context->svgAttributeChanged(imp->associatedAttributeName());48 JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); 48 49 return jsUndefined(); 49 50 } … … 54 55 SVGPathSeg* newItem = toSVGPathSeg(args.at(0)); 55 56 56 SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl());57 SVGPathSegList* list = impl(); 57 58 58 SVGPathSeg* obj = WTF::getPtr(imp->initialize(newItem, ec)); 59 SVGPathSeg* obj = WTF::getPtr(list->initialize(newItem, ec)); 60 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 59 61 60 JS C::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get());62 JSValue result = toJS(exec, globalObject(), obj, context); 61 63 setDOMException(exec, ec); 62 64 63 m_context->svgAttributeChanged(imp->associatedAttributeName());65 JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); 64 66 return result; 65 67 } … … 76 78 } 77 79 78 SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); 79 SVGPathSeg* obj = WTF::getPtr(imp->getItem(index, ec)); 80 SVGPathSegList* list = impl(); 81 SVGPathSeg* obj = WTF::getPtr(list->getItem(index, ec)); 82 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 80 83 81 JS C::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get());84 JSValue result = toJS(exec, globalObject(), obj, context); 82 85 setDOMException(exec, ec); 83 86 return result; … … 96 99 } 97 100 98 SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); 101 SVGPathSegList* list = impl(); 102 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 99 103 100 JS C::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->insertItemBefore(newItem, index, ec)), m_context.get());104 JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->insertItemBefore(newItem, index, ec)), context); 101 105 setDOMException(exec, ec); 102 106 103 m_context->svgAttributeChanged(imp->associatedAttributeName());107 JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); 104 108 return result; 105 109 } … … 117 121 } 118 122 119 SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); 123 SVGPathSegList* list = impl(); 124 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 120 125 121 JS C::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->replaceItem(newItem, index, ec)), m_context.get());126 JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->replaceItem(newItem, index, ec)), context); 122 127 setDOMException(exec, ec); 123 128 124 m_context->svgAttributeChanged(imp->associatedAttributeName());129 JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); 125 130 return result; 126 131 } … … 137 142 } 138 143 139 SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl());144 SVGPathSegList* list = impl(); 140 145 141 RefPtr<SVGPathSeg> obj(imp->removeItem(index, ec)); 146 RefPtr<SVGPathSeg> obj(list->removeItem(index, ec)); 147 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 142 148 143 JS C::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj.get(), m_context.get());149 JSValue result = toJS(exec, globalObject(), obj.get(), context); 144 150 setDOMException(exec, ec); 145 151 146 m_context->svgAttributeChanged(imp->associatedAttributeName());152 JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); 147 153 return result; 148 154 } … … 153 159 SVGPathSeg* newItem = toSVGPathSeg(args.at(0)); 154 160 155 SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); 161 SVGPathSegList* list = impl(); 162 SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); 156 163 157 JS C::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->appendItem(newItem, ec)), m_context.get());164 JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->appendItem(newItem, ec)), context); 158 165 setDOMException(exec, ec); 159 166 160 m_context->svgAttributeChanged(imp->associatedAttributeName());167 JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); 161 168 return result; 162 169 } -
trunk/WebCore/bindings/scripts/CodeGeneratorJS.pm
r53574 r53666 133 133 134 134 return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"}; 135 if (@{$dataNode->parents} eq 0) { 136 # FIXME: SVG types requiring a context() pointer do not have enough 137 # space to hold a globalObject pointer as well w/o hitting the CELL_SIZE limit. 138 # This could be fixed by moving context() into the various impl() classes. 139 # Until then, we special case these SVG bindings and allow them to return 140 # the wrong prototypes and constructors during x-frame access. See bug 27088. 141 return "DOMObjectWithSVGContext" if IsSVGTypeNeedingContextParameter($dataNode->name); 142 return "DOMObjectWithGlobalPointer"; 143 } 135 return "DOMObjectWithGlobalPointer" if (@{$dataNode->parents} eq 0); 144 136 return "JS" . $codeGenerator->StripModule($dataNode->parents(0)); 145 137 } … … 168 160 return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration"; 169 161 return 0; 170 }171 172 sub CreateSVGContextInterfaceName173 {174 my $type = shift;175 176 return $type if $codeGenerator->IsSVGAnimatedType($type);177 return "SVGPathSeg" if $type =~ /^SVGPathSeg/ and $type ne "SVGPathSegList";178 179 return "";180 162 } 181 163 … … 494 476 my $parentClassName = GetParentClassName($dataNode); 495 477 my $conditional = $dataNode->extendedAttributes->{"Conditional"}; 496 my $needsSVGContext = IsSVGTypeNeedingContextParameter($interfaceName);497 478 my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; 498 479 my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; … … 514 495 $headerIncludes{"$parentClassName.h"} = 1; 515 496 } else { 516 $headerIncludes{"DOMObjectWithSVGContext.h"} = $needsSVGContext; 517 $headerIncludes{"JSDOMBinding.h"} = !$needsSVGContext; 497 $headerIncludes{"JSDOMBinding.h"} = 1; 518 498 $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1; 519 499 $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1; … … 562 542 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { 563 543 push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n"); 564 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {565 push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>, SVGElement* context);\n");566 544 } else { 567 545 push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n"); … … 784 762 if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) { 785 763 if ($podType) { 786 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n");764 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement*);\n"); 787 765 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 788 766 push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n"); … … 1174 1152 my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; 1175 1153 1176 my $needsSVGContext = IsSVGTypeNeedingContextParameter($implClassName);1177 my $parentNeedsSVGContext = ($needsSVGContext and $parentClassName =~ /SVG/);1178 1179 1154 # Constructor 1180 1155 if ($interfaceName eq "DOMWindow") { … … 1187 1162 push(@implContent, " : $parentClassName(structure, impl)\n"); 1188 1163 } else { 1189 my $contextArg = $needsSVGContext ? ", SVGElement* context" : ""; 1190 push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl$contextArg)\n"); 1164 push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); 1191 1165 if ($hasParent) { 1192 push(@implContent, " : $parentClassName(structure, globalObject, impl " . ($parentNeedsSVGContext ? ", context" : "") . ")\n");1166 push(@implContent, " : $parentClassName(structure, globalObject, impl)\n"); 1193 1167 } else { 1194 push(@implContent, " : $parentClassName(structure, globalObject " . ($needsSVGContext ? ", context" : "") . ")\n");1168 push(@implContent, " : $parentClassName(structure, globalObject)\n"); 1195 1169 push(@implContent, " , m_impl(impl)\n"); 1196 1170 } … … 1215 1189 push(@implContent, " forgetDOMObject(this, impl());\n"); 1216 1190 } 1191 1192 push(@implContent, " JSSVGContextCache::forgetWrapper(this);\n") if IsSVGTypeNeedingContextParameter($implClassName); 1217 1193 } 1218 1194 … … 1396 1372 push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); 1397 1373 push(@implContent, "{\n"); 1398 if (IsSVGTypeNeedingContextParameter($interfaceName)) { 1399 # FIXME: SVG bindings with a context pointer have no space to store a globalObject 1400 # so we use deprecatedGlobalObjectForPrototype instead. 1401 push(@implContent, " UNUSED_PARAM(slot);\n"); 1402 push(@implContent, " return ${className}::getConstructor(exec, deprecatedGlobalObjectForPrototype(exec));\n"); 1403 } else { 1404 push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); 1405 push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); 1406 } 1374 push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); 1375 push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); 1407 1376 push(@implContent, "}\n"); 1408 1377 } … … 1489 1458 push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n"); 1490 1459 } else { 1460 push(@implContent, " $className* castedThisObj = static_cast<$className*>(thisObject);\n"); 1461 push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); 1491 1462 if ($podType) { 1492 push(@implContent, " $podType imp(*static_cast<$className*>(thisObject)->impl());\n");1463 push(@implContent, " $podType podImp(*imp);\n"); 1493 1464 if ($podType eq "float") { # Special case for JSSVGNumber 1494 push(@implContent, " imp = " . JSValueToNative($attribute->signature, "value") . ";\n");1465 push(@implContent, " podImp = " . JSValueToNative($attribute->signature, "value") . ";\n"); 1495 1466 } else { 1496 push(@implContent, " imp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n");1467 push(@implContent, " podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n"); 1497 1468 } 1498 push(@implContent, " static_cast<$className*>(thisObject)->impl()->commitChange(imp, static_cast<$className*>(thisObject)->context());\n");1469 push(@implContent, " imp->commitChange(podImp, castedThisObj);\n"); 1499 1470 } else { 1500 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n");1501 1471 my $nativeValue = JSValueToNative($attribute->signature, "value"); 1502 1472 push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; … … 1514 1484 push(@implContent, ");\n"); 1515 1485 push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; 1516 1517 1486 if (IsSVGTypeNeedingContextParameter($implClassName)) { 1518 push(@implContent, " if (static_cast<$className*>(thisObject)->context())\n"); 1519 push(@implContent, " static_cast<$className*>(thisObject)->context()->svgAttributeChanged(static_cast<$className*>(thisObject)->impl()->associatedAttributeName());\n"); 1487 push(@implContent, " JSSVGContextCache::propagateSVGDOMChange(castedThisObj, imp->associatedAttributeName());\n"); 1520 1488 } 1521 1489 } … … 1603 1571 . ">(castedThisObj, exec, args, to" . $svgPODListType . ");\n"); 1604 1572 } else { 1605 if ($podType) { 1606 push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n"); 1607 push(@implContent, " $podType imp(*wrapper);\n"); 1608 } else { 1609 push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n"); 1610 } 1573 push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); 1574 push(@implContent, " $podType podImp(*imp);\n") if $podType; 1611 1575 1612 1576 my $numParameters = @{$function->parameters}; … … 1628 1592 1629 1593 my $paramIndex = 0; 1630 my $functionString = "imp" . ($podType ? "." : "->") . $functionImplementationName . "(";1594 my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "("; 1631 1595 1632 1596 my $hasOptionalArguments = 0; … … 1739 1703 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n"); 1740 1704 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { 1741 1705 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n"); 1742 1706 } else { 1743 1707 push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n"); 1744 1708 } 1745 1746 1709 push(@implContent, "{\n"); 1747 1710 if ($podType) { … … 1801 1764 push(@implContent, $indent . "$functionString;\n"); 1802 1765 push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; 1803 1804 if ($podType) { 1805 push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n"); 1806 } 1807 1766 push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n") if $podType; 1808 1767 push(@implContent, $indent . "return jsUndefined();\n"); 1809 1768 } else { … … 1814 1773 # Immutable methods do not commit changes back to the instance, thus producing 1815 1774 # a new instance rather than mutating existing one. 1816 push(@implContent, $indent . " wrapper->commitChange(imp, castedThisObj->context());\n");1775 push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n"); 1817 1776 } 1818 1777 … … 1938 1897 } 1939 1898 1940 # Some SVG bindings don't have space to store a globalObject pointer, for those, we use the deprecatedGlobalObjectForPrototype hack for now. 1941 my $globalObject = IsSVGTypeNeedingContextParameter($implClassName) ? "deprecatedGlobalObjectForPrototype(exec)" : "$thisValue->globalObject()"; 1942 1899 my $globalObject = "$thisValue->globalObject()"; 1943 1900 if ($codeGenerator->IsPodType($type)) { 1944 1901 $implIncludes{"JS$type.h"} = 1; … … 1958 1915 and not defined $signature->extendedAttributes->{"Immutable"}) { 1959 1916 if ($codeGenerator->IsPodType($implClassName)) { 1960 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), $thisValue->context())";1917 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), JSSVGContextCache::svgContextForDOMObject(castedThis))"; 1961 1918 } else { 1962 1919 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)"; … … 1965 1922 1966 1923 if ($implClassNameForValueConversion eq "") { 1967 # SVGZoomEvent has no context() pointer, and is also not an SVGElement. 1968 # This is not a problem, because SVGZoomEvent has no read/write properties. 1969 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0)" if $implClassName eq "SVGZoomEvent"; 1970 1971 if (IsSVGTypeNeedingContextParameter($implClassName)) { 1972 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), castedThisObj->context())" if $inFunctionCall; 1973 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), $thisValue->context())"; 1974 } else { 1975 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), imp)"; 1976 } 1977 } else { # These classes, always have a m_context pointer! 1978 return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), $thisValue->context())"; 1924 return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0 /* no context on purpose */)"; 1925 } else { 1926 return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), JSSVGContextCache::svgContextForDOMObject(castedThis));" 1979 1927 } 1980 1928 } … … 2017 1965 2018 1966 if (IsSVGTypeNeedingContextParameter($type)) { 2019 my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? " $thisValue->context()" : "imp";1967 my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "JSSVGContextCache::svgContextForDOMObject(castedThis)" : "imp"; 2020 1968 return "toJS(exec, $globalObject, WTF::getPtr($value), $contextPtr)"; 2021 1969 } -
trunk/WebCore/svg/SVGAngle.h
r52373 r53666 28 28 namespace WebCore { 29 29 30 class SVGStyledElement;31 32 30 class SVGAngle { 33 31 public: … … 57 55 void convertToSpecifiedUnits(unsigned short unitType); 58 56 59 // Throughout SVG 1.1 'SVGAngle' is only used for 'SVGMarkerElement' (orient-angle)60 const QualifiedName& associatedAttributeName() const { return SVGNames::orientAttr; }61 62 57 private: 63 58 SVGAngleType m_unitType; -
trunk/WebCore/svg/SVGPreserveAspectRatio.h
r52865 r53666 85 85 String valueAsString() const; 86 86 87 const QualifiedName& associatedAttributeName() const { return SVGNames::preserveAspectRatioAttr; }88 89 87 private: 90 88 unsigned short m_align; -
trunk/WebCore/svg/SVGTransform.h
r50583 r53666 55 55 FloatPoint rotationCenter() const; 56 56 57 // void setMatrix(const TransformationMatrix&);58 57 void setMatrix(TransformationMatrix); 59 58 … … 69 68 70 69 bool isValid(); 71 72 // Throughout SVG 1.1 'SVGTransform' is only used for the 'transform' attribute73 const QualifiedName& associatedAttributeName() const { return SVGNames::transformAttr; }74 70 75 71 private: … … 94 90 #endif // ENABLE(SVG) 95 91 #endif 96 97 // vim:ts=4:noet
Note: See TracChangeset
for help on using the changeset viewer.