Remove the CREATE_DOM_WRAPPER macro
https://bugs.webkit.org/show_bug.cgi?id=161580

Reviewed by Dan Bernstein.

The CREATE_DOM_WRAPPER has irritated me for too long! Replace it
with direct calls to createWrapper<ImplementationType>, which has
been upgraded to not require specifying both the implementation type
and the wrapper type by way of the new JSDOMWrapperConverterTraits
struct which provides mapping from ImplementationType -> JSWrapper.
createWrapper<ImplementationType> has also been upgraded to have a
specialization for when the object being passed in needs to be casted.

* bindings/js/JSAnimationTimelineCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSBlobCustom.cpp:
(WebCore::toJSNewlyCreated):
(WebCore::constructJSBlob):
* bindings/js/JSCSSRuleCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSCSSValueCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSDataCueCustom.cpp:
(WebCore::constructJSDataCue):
* bindings/js/JSDocumentCustom.cpp:
(WebCore::createNewDocumentWrapper):
* bindings/js/JSDocumentFragmentCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSElementCustom.cpp:
(WebCore::createNewElementWrapper):
* bindings/js/JSEventCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSFileCustom.cpp:
(WebCore::constructJSFile):
* bindings/js/JSHTMLCollectionCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSHTMLDocumentCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSIDBCursorCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSImageDataCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSNodeCustom.cpp:
(WebCore::createWrapperInline):
* bindings/js/JSNodeListCustom.cpp:
(WebCore::createWrapper):
* bindings/js/JSPerformanceEntryCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSSVGPathSegCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSStyleSheetCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSTextCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSTextTrackCueCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSWebGLRenderingContextBaseCustom.cpp:
(WebCore::toJSNewlyCreated):
* bindings/js/JSXMLDocumentCustom.cpp:
(WebCore::toJSNewlyCreated):
* dom/make_names.pl:
(printWrapperFunctions):
(printWrapperFactoryCppFile):
Replace CREATE_DOM_WRAPPER with direct calls to createWrapper.

* bindings/js/JSWorkerGlobalScopeBase.h:
Add #include of JSDOMWrapper.h to allow generated subclasses to use 
JSDOMWrapperConverterTraits.

* bindings/js/JSDOMBinding.h:
(WebCore::castDOMObjectForWrapperCreation): Deleted.
Remove CREATE_DOM_WRAPPER and castDOMObjectForWrapperCreation and 
specialize createWrapper.

* bindings/js/JSDOMWrapper.h:
Forward declare JSDOMWrapperConverterTraits.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
Add specialization of JSDOMWrapperConverterTraits for each header.

(GenerateImplementation):
(GenerateConstructorDefinition):
Replace CREATE_DOM_WRAPPER with direct calls to createWrapper.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@205422 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp b/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp
index c6593e4..47df4e7 100644
--- a/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp
+++ b/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp
@@ -42,8 +42,8 @@
 JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<AnimationTimeline>&& value)
 {
     if (value->isDocumentTimeline())
-        return CREATE_DOM_WRAPPER(globalObject, DocumentTimeline, WTFMove(value));
-    return CREATE_DOM_WRAPPER(globalObject, AnimationTimeline, WTFMove(value));
+        return createWrapper<DocumentTimeline>(globalObject, WTFMove(value));
+    return createWrapper<AnimationTimeline>(globalObject, WTFMove(value));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, AnimationTimeline& value)
diff --git a/Source/WebCore/bindings/js/JSBlobCustom.cpp b/Source/WebCore/bindings/js/JSBlobCustom.cpp
index a169a21..68e1f19 100644
--- a/Source/WebCore/bindings/js/JSBlobCustom.cpp
+++ b/Source/WebCore/bindings/js/JSBlobCustom.cpp
@@ -53,8 +53,8 @@
 JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<Blob>&& blob)
 {
     if (is<File>(blob))
-        return CREATE_DOM_WRAPPER(globalObject, File, WTFMove(blob));
-    return createWrapper<JSBlob>(globalObject, WTFMove(blob));
+        return createWrapper<File>(globalObject, WTFMove(blob));
+    return createWrapper<Blob>(globalObject, WTFMove(blob));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Blob& blob)
@@ -75,7 +75,7 @@
         return throwConstructorScriptExecutionContextUnavailableError(exec, scope, "Blob");
 
     if (!exec.argumentCount()) {
-        return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), Blob, Blob::create()));
+        return JSValue::encode(createWrapper<Blob>(jsConstructor->globalObject(), Blob::create()));
     }
 
     unsigned blobPartsLength = 0;
@@ -139,7 +139,7 @@
     }
 
     auto blob = Blob::create(blobBuilder.finalize(), Blob::normalizedContentType(type));
-    return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), Blob, WTFMove(blob)));
+    return JSValue::encode(createWrapper<Blob>(jsConstructor->globalObject(), WTFMove(blob)));
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
index 8dc19b5..b1d0ce5 100644
--- a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
@@ -64,33 +64,33 @@
 {
     switch (rule->type()) {
     case CSSRule::STYLE_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSStyleRule, WTFMove(rule));
+        return createWrapper<CSSStyleRule>(globalObject, WTFMove(rule));
     case CSSRule::MEDIA_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSMediaRule, WTFMove(rule));
+        return createWrapper<CSSMediaRule>(globalObject, WTFMove(rule));
     case CSSRule::FONT_FACE_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSFontFaceRule, WTFMove(rule));
+        return createWrapper<CSSFontFaceRule>(globalObject, WTFMove(rule));
     case CSSRule::PAGE_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSPageRule, WTFMove(rule));
+        return createWrapper<CSSPageRule>(globalObject, WTFMove(rule));
     case CSSRule::IMPORT_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSImportRule, WTFMove(rule));
+        return createWrapper<CSSImportRule>(globalObject, WTFMove(rule));
     case CSSRule::CHARSET_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSCharsetRule, WTFMove(rule));
+        return createWrapper<CSSCharsetRule>(globalObject, WTFMove(rule));
     case CSSRule::KEYFRAME_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSKeyframeRule, WTFMove(rule));
+        return createWrapper<CSSKeyframeRule>(globalObject, WTFMove(rule));
     case CSSRule::KEYFRAMES_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSKeyframesRule, WTFMove(rule));
+        return createWrapper<CSSKeyframesRule>(globalObject, WTFMove(rule));
     case CSSRule::SUPPORTS_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, CSSSupportsRule, WTFMove(rule));
+        return createWrapper<CSSSupportsRule>(globalObject, WTFMove(rule));
 #if ENABLE(CSS_DEVICE_ADAPTATION)
     case CSSRule::WEBKIT_VIEWPORT_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSViewportRule, WTFMove(rule));
+        return createWrapper<WebKitCSSViewportRule>(globalObject, WTFMove(rule));
 #endif
 #if ENABLE(CSS_REGIONS)
     case CSSRule::WEBKIT_REGION_RULE:
-        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSRegionRule, WTFMove(rule));
+        return createWrapper<WebKitCSSRegionRule>(globalObject, WTFMove(rule));
 #endif
     default:
-        return CREATE_DOM_WRAPPER(globalObject, CSSRule, WTFMove(rule));
+        return createWrapper<CSSRule>(globalObject, WTFMove(rule));
     }
 }
 
diff --git a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
index 43b136f..c5ab306 100644
--- a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
@@ -67,18 +67,18 @@
 JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<CSSValue>&& value)
 {
     if (value->isWebKitCSSTransformValue())
-        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSTransformValue, WTFMove(value));
+        return createWrapper<WebKitCSSTransformValue>(globalObject, WTFMove(value));
     if (value->isWebKitCSSFilterValue())
-        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSFilterValue, WTFMove(value));
+        return createWrapper<WebKitCSSFilterValue>(globalObject, WTFMove(value));
     if (value->isValueList())
-        return CREATE_DOM_WRAPPER(globalObject, CSSValueList, WTFMove(value));
+        return createWrapper<CSSValueList>(globalObject, WTFMove(value));
     if (value->isSVGPaint())
-        return CREATE_DOM_WRAPPER(globalObject, SVGPaint, WTFMove(value));
+        return createWrapper<SVGPaint>(globalObject, WTFMove(value));
     if (value->isSVGColor())
-        return CREATE_DOM_WRAPPER(globalObject, SVGColor, WTFMove(value));
+        return createWrapper<SVGColor>(globalObject, WTFMove(value));
     if (value->isPrimitiveValue())
-        return CREATE_DOM_WRAPPER(globalObject, CSSPrimitiveValue, WTFMove(value));
-    return CREATE_DOM_WRAPPER(globalObject, CSSValue, WTFMove(value));
+        return createWrapper<CSSPrimitiveValue>(globalObject, WTFMove(value));
+    return createWrapper<CSSValue>(globalObject, WTFMove(value));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, CSSValue& value)
diff --git a/Source/WebCore/bindings/js/JSDOMBinding.h b/Source/WebCore/bindings/js/JSDOMBinding.h
index a4e0bc3..0b358e9 100644
--- a/Source/WebCore/bindings/js/JSDOMBinding.h
+++ b/Source/WebCore/bindings/js/JSDOMBinding.h
@@ -162,14 +162,12 @@
 bool clearInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*, JSDOMObject* wrapper);
 bool clearInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*, JSC::JSArrayBuffer* wrapper);
 
-template<typename DOMClass, typename T> Ref<DOMClass> inline castDOMObjectForWrapperCreation(Ref<T>&& object) { return static_reference_cast<DOMClass>(WTFMove(object)); }
-#define CREATE_DOM_WRAPPER(globalObject, className, object) createWrapper<JS##className, className>(globalObject, castDOMObjectForWrapperCreation<className>(object))
-
 template<typename DOMClass> JSC::JSObject* getCachedWrapper(DOMWrapperWorld&, DOMClass&);
 template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, Ref<DOMClass>& object) { return getCachedWrapper(world, object.get()); }
 template<typename DOMClass, typename WrapperClass> void cacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*);
 template<typename DOMClass, typename WrapperClass> void uncacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*);
-template<typename WrapperClass, typename DOMClass> WrapperClass* createWrapper(JSDOMGlobalObject*, Ref<DOMClass>&&);
+template<typename DOMClass, typename T> auto createWrapper(JSDOMGlobalObject*, Ref<T>&&) -> typename std::enable_if<std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type;
+template<typename DOMClass, typename T> auto createWrapper(JSDOMGlobalObject*, Ref<T>&&) -> typename std::enable_if<!std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type;
 
 template<typename DOMClass> JSC::JSValue wrap(JSC::ExecState*, JSDOMGlobalObject*, DOMClass&);
 
@@ -471,15 +469,22 @@
     weakRemove(world.m_wrappers, wrapperKey(domObject), wrapper);
 }
 
-template<typename WrapperClass, typename DOMClass> inline WrapperClass* createWrapper(JSDOMGlobalObject* globalObject, Ref<DOMClass>&& node)
+template<typename DOMClass, typename T> inline auto createWrapper(JSDOMGlobalObject* globalObject, Ref<T>&& domObject) -> typename std::enable_if<std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type
 {
-    ASSERT(!getCachedWrapper(globalObject->world(), node));
-    auto* nodePtr = node.ptr();
-    WrapperClass* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(globalObject->vm(), *globalObject), globalObject, WTFMove(node));
-    cacheWrapper(globalObject->world(), nodePtr, wrapper);
+    using WrapperClass = typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass;
+
+    ASSERT(!getCachedWrapper(globalObject->world(), domObject));
+    auto* domObjectPtr = domObject.ptr();
+    auto* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(globalObject->vm(), *globalObject), globalObject, WTFMove(domObject));
+    cacheWrapper(globalObject->world(), domObjectPtr, wrapper);
     return wrapper;
 }
 
+template<typename DOMClass, typename T> inline auto createWrapper(JSDOMGlobalObject* globalObject, Ref<T>&& domObject) -> typename std::enable_if<!std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type
+{
+    return createWrapper<DOMClass>(globalObject, static_reference_cast<DOMClass>(WTFMove(domObject)));
+}
+
 template<typename DOMClass> inline JSC::JSValue wrap(JSC::ExecState* state, JSDOMGlobalObject* globalObject, DOMClass& domObject)
 {
     if (auto* wrapper = getCachedWrapper(globalObject->world(), domObject))
diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.h b/Source/WebCore/bindings/js/JSDOMWrapper.h
index 715601e..22a2a2c 100644
--- a/Source/WebCore/bindings/js/JSDOMWrapper.h
+++ b/Source/WebCore/bindings/js/JSDOMWrapper.h
@@ -66,6 +66,8 @@
     Ref<ImplementationClass> m_wrapped;
 };
 
+template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;
+
 template<typename JSClass, typename Enable = void>
 struct JSDOMObjectInspector {
 public:
diff --git a/Source/WebCore/bindings/js/JSDataCueCustom.cpp b/Source/WebCore/bindings/js/JSDataCueCustom.cpp
index 99ef005..3dc26a5 100644
--- a/Source/WebCore/bindings/js/JSDataCueCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDataCueCustom.cpp
@@ -94,13 +94,13 @@
             setDOMException(&exec, TypeError);
             return JSValue::encode(jsUndefined());
         }
-        return JSValue::encode(CREATE_DOM_WRAPPER(castedThis->globalObject(), DataCue, DataCue::create(*context, MediaTime::createWithDouble(startTime), MediaTime::createWithDouble(endTime), *data, type)));
+        return JSValue::encode(createWrapper<DataCue>(castedThis->globalObject(), DataCue::create(*context, MediaTime::createWithDouble(startTime), MediaTime::createWithDouble(endTime), *data, type)));
     }
 
 #if !ENABLE(DATACUE_VALUE)
     return JSValue::encode(jsUndefined());
 #else
-    return JSValue::encode(CREATE_DOM_WRAPPER(castedThis->globalObject(), DataCue,DataCue::create(*context, MediaTime::createWithDouble(startTime), MediaTime::createWithDouble(endTime), valueArgument, type)));
+    return JSValue::encode(createWrapper<DataCue>(castedThis->globalObject(), DataCue::create(*context, MediaTime::createWithDouble(startTime), MediaTime::createWithDouble(endTime), valueArgument, type)));
 #endif
 }
 
diff --git a/Source/WebCore/bindings/js/JSDocumentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentCustom.cpp
index 6ea19db..746e008 100644
--- a/Source/WebCore/bindings/js/JSDocumentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDocumentCustom.cpp
@@ -57,11 +57,11 @@
     auto& document = passedDocument.get();
     JSObject* wrapper;
     if (document.isHTMLDocument())
-        wrapper = CREATE_DOM_WRAPPER(&globalObject, HTMLDocument, WTFMove(passedDocument));
+        wrapper = createWrapper<HTMLDocument>(&globalObject, WTFMove(passedDocument));
     else if (document.isXMLDocument())
-        wrapper = CREATE_DOM_WRAPPER(&globalObject, XMLDocument, WTFMove(passedDocument));
+        wrapper = createWrapper<XMLDocument>(&globalObject, WTFMove(passedDocument));
     else
-        wrapper = CREATE_DOM_WRAPPER(&globalObject, Document, WTFMove(passedDocument));
+        wrapper = createWrapper<Document>(&globalObject, WTFMove(passedDocument));
 
     reportMemoryForDocumentIfFrameless(state, document);
 
diff --git a/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp
index b829dd2..8df8ee7 100644
--- a/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp
@@ -55,8 +55,8 @@
 JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<DocumentFragment>&& impl)
 {
     if (impl->isShadowRoot())
-        return CREATE_DOM_WRAPPER(globalObject, ShadowRoot, WTFMove(impl));
-    return createWrapper<JSDocumentFragment>(globalObject, WTFMove(impl));
+        return createWrapper<ShadowRoot>(globalObject, WTFMove(impl));
+    return createWrapper<DocumentFragment>(globalObject, WTFMove(impl));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, DocumentFragment& impl)
diff --git a/Source/WebCore/bindings/js/JSElementCustom.cpp b/Source/WebCore/bindings/js/JSElementCustom.cpp
index e5d41bc..62e5392 100644
--- a/Source/WebCore/bindings/js/JSElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSElementCustom.cpp
@@ -55,7 +55,7 @@
         return createJSHTMLWrapper(globalObject, static_reference_cast<HTMLElement>(WTFMove(element)));
     if (is<SVGElement>(element.get()))
         return createJSSVGWrapper(globalObject, static_reference_cast<SVGElement>(WTFMove(element)));
-    return CREATE_DOM_WRAPPER(globalObject, Element, WTFMove(element));
+    return createWrapper<Element>(globalObject, WTFMove(element));
 }
 
 JSValue toJS(ExecState*, JSDOMGlobalObject* globalObject, Element& element)
diff --git a/Source/WebCore/bindings/js/JSEventCustom.cpp b/Source/WebCore/bindings/js/JSEventCustom.cpp
index acfb599..015ca6b 100644
--- a/Source/WebCore/bindings/js/JSEventCustom.cpp
+++ b/Source/WebCore/bindings/js/JSEventCustom.cpp
@@ -50,7 +50,7 @@
 
 #define TRY_TO_WRAP_WITH_INTERFACE(interfaceName) \
     case interfaceName##InterfaceType: \
-        return CREATE_DOM_WRAPPER(globalObject, interfaceName, WTFMove(event));
+        return createWrapper<interfaceName>(globalObject, WTFMove(event));
 
 JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Event>&& event)
 {
@@ -58,7 +58,7 @@
         DOM_EVENT_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE)
     }
 
-    return CREATE_DOM_WRAPPER(globalObject, Event, WTFMove(event));
+    return createWrapper<Event>(globalObject, WTFMove(event));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Event& event)
diff --git a/Source/WebCore/bindings/js/JSFileCustom.cpp b/Source/WebCore/bindings/js/JSFileCustom.cpp
index 59611c0..1a42cf8 100644
--- a/Source/WebCore/bindings/js/JSFileCustom.cpp
+++ b/Source/WebCore/bindings/js/JSFileCustom.cpp
@@ -125,7 +125,7 @@
     }
 
     auto file = File::create(blobBuilder.finalize(), filename, normalizedType, lastModified.value());
-    return JSValue::encode(CREATE_DOM_WRAPPER(constructor->globalObject(), File, WTFMove(file)));
+    return JSValue::encode(createWrapper<File>(constructor->globalObject(), WTFMove(file)));
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
index 41ef9c3..e398a85 100644
--- a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
@@ -56,16 +56,16 @@
 {
     switch (collection->type()) {
     case FormControls:
-        return CREATE_DOM_WRAPPER(globalObject, HTMLFormControlsCollection, WTFMove(collection));
+        return createWrapper<HTMLFormControlsCollection>(globalObject, WTFMove(collection));
     case SelectOptions:
-        return CREATE_DOM_WRAPPER(globalObject, HTMLOptionsCollection, WTFMove(collection));
+        return createWrapper<HTMLOptionsCollection>(globalObject, WTFMove(collection));
     case DocAll:
-        return CREATE_DOM_WRAPPER(globalObject, HTMLAllCollection, WTFMove(collection));
+        return createWrapper<HTMLAllCollection>(globalObject, WTFMove(collection));
     default:
         break;
     }
 
-    return CREATE_DOM_WRAPPER(globalObject, HTMLCollection, WTFMove(collection));
+    return createWrapper<HTMLCollection>(globalObject, WTFMove(collection));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, HTMLCollection& collection)
diff --git a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
index 67670f8..7cfc05f 100644
--- a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
@@ -56,7 +56,7 @@
 JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<HTMLDocument>&& passedDocument)
 {
     auto& document = passedDocument.get();
-    JSObject* wrapper = createWrapper<JSHTMLDocument>(globalObject, WTFMove(passedDocument));
+    JSObject* wrapper = createWrapper<HTMLDocument>(globalObject, WTFMove(passedDocument));
 
     reportMemoryForDocumentIfFrameless(*state, document);
 
diff --git a/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp
index bfc18f1..4aa505f 100644
--- a/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp
+++ b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp
@@ -55,8 +55,8 @@
 JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<IDBCursor>&& cursor)
 {
     if (is<IDBCursorWithValue>(cursor))
-        return CREATE_DOM_WRAPPER(globalObject, IDBCursorWithValue, WTFMove(cursor));
-    return createWrapper<JSIDBCursor>(globalObject, WTFMove(cursor));
+        return createWrapper<IDBCursorWithValue>(globalObject, WTFMove(cursor));
+    return createWrapper<IDBCursor>(globalObject, WTFMove(cursor));
 }
 
 JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, IDBCursor& cursor)
diff --git a/Source/WebCore/bindings/js/JSImageDataCustom.cpp b/Source/WebCore/bindings/js/JSImageDataCustom.cpp
index 870826c..a25c865 100644
--- a/Source/WebCore/bindings/js/JSImageDataCustom.cpp
+++ b/Source/WebCore/bindings/js/JSImageDataCustom.cpp
@@ -38,7 +38,7 @@
 JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<ImageData>&& imageData)
 {
     auto* data = imageData->data();
-    auto* wrapper = CREATE_DOM_WRAPPER(globalObject, ImageData, WTFMove(imageData));
+    auto* wrapper = createWrapper<ImageData>(globalObject, WTFMove(imageData));
     Identifier dataName = Identifier::fromString(state, "data");
     wrapper->putDirect(state->vm(), dataName, toJS(state, globalObject, data), DontDelete | ReadOnly);
     // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
diff --git a/Source/WebCore/bindings/js/JSNodeCustom.cpp b/Source/WebCore/bindings/js/JSNodeCustom.cpp
index 43cfcf0..c8319ea 100644
--- a/Source/WebCore/bindings/js/JSNodeCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeCustom.cpp
@@ -224,37 +224,37 @@
             else if (is<SVGElement>(node.get()))
                 wrapper = createJSSVGWrapper(globalObject, static_reference_cast<SVGElement>(WTFMove(node)));
             else
-                wrapper = CREATE_DOM_WRAPPER(globalObject, Element, WTFMove(node));
+                wrapper = createWrapper<Element>(globalObject, WTFMove(node));
             break;
         case Node::ATTRIBUTE_NODE:
-            wrapper = CREATE_DOM_WRAPPER(globalObject, Attr, WTFMove(node));
+            wrapper = createWrapper<Attr>(globalObject, WTFMove(node));
             break;
         case Node::TEXT_NODE:
-            wrapper = CREATE_DOM_WRAPPER(globalObject, Text, WTFMove(node));
+            wrapper = createWrapper<Text>(globalObject, WTFMove(node));
             break;
         case Node::CDATA_SECTION_NODE:
-            wrapper = CREATE_DOM_WRAPPER(globalObject, CDATASection, WTFMove(node));
+            wrapper = createWrapper<CDATASection>(globalObject, WTFMove(node));
             break;
         case Node::PROCESSING_INSTRUCTION_NODE:
-            wrapper = CREATE_DOM_WRAPPER(globalObject, ProcessingInstruction, WTFMove(node));
+            wrapper = createWrapper<ProcessingInstruction>(globalObject, WTFMove(node));
             break;
         case Node::COMMENT_NODE:
-            wrapper = CREATE_DOM_WRAPPER(globalObject, Comment, WTFMove(node));
+            wrapper = createWrapper<Comment>(globalObject, WTFMove(node));
             break;
         case Node::DOCUMENT_NODE:
             // we don't want to cache the document itself in the per-document dictionary
             return toJS(exec, globalObject, downcast<Document>(node.get()));
         case Node::DOCUMENT_TYPE_NODE:
-            wrapper = CREATE_DOM_WRAPPER(globalObject, DocumentType, WTFMove(node));
+            wrapper = createWrapper<DocumentType>(globalObject, WTFMove(node));
             break;
         case Node::DOCUMENT_FRAGMENT_NODE:
             if (node->isShadowRoot())
-                wrapper = CREATE_DOM_WRAPPER(globalObject, ShadowRoot, WTFMove(node));
+                wrapper = createWrapper<ShadowRoot>(globalObject, WTFMove(node));
             else
-                wrapper = CREATE_DOM_WRAPPER(globalObject, DocumentFragment, WTFMove(node));
+                wrapper = createWrapper<DocumentFragment>(globalObject, WTFMove(node));
             break;
         default:
-            wrapper = CREATE_DOM_WRAPPER(globalObject, Node, WTFMove(node));
+            wrapper = createWrapper<Node>(globalObject, WTFMove(node));
     }
 
     return wrapper;
diff --git a/Source/WebCore/bindings/js/JSNodeListCustom.cpp b/Source/WebCore/bindings/js/JSNodeListCustom.cpp
index 0900537..513bbdf 100644
--- a/Source/WebCore/bindings/js/JSNodeListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeListCustom.cpp
@@ -56,7 +56,7 @@
     // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
     // https://bugs.webkit.org/show_bug.cgi?id=142595
     globalObject.vm().heap.deprecatedReportExtraMemory(nodeList->memoryCost());
-    return createWrapper<JSNodeList>(&globalObject, WTFMove(nodeList));
+    return createWrapper<NodeList>(&globalObject, WTFMove(nodeList));
 }
 
 JSC::JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<NodeList>&& nodeList)
diff --git a/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp b/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp
index 2d665a9..43712cc 100644
--- a/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp
+++ b/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp
@@ -50,17 +50,17 @@
 JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<PerformanceEntry>&& entry)
 {
     if (is<PerformanceResourceTiming>(entry))
-        return CREATE_DOM_WRAPPER(globalObject, PerformanceResourceTiming, WTFMove(entry));
+        return createWrapper<PerformanceResourceTiming>(globalObject, WTFMove(entry));
 
 #if ENABLE(USER_TIMING)
     if (is<PerformanceMark>(entry))
-        return CREATE_DOM_WRAPPER(globalObject, PerformanceMark, WTFMove(entry));
+        return createWrapper<PerformanceMark>(globalObject, WTFMove(entry));
 
     if (is<PerformanceMeasure>(entry))
-        return CREATE_DOM_WRAPPER(globalObject, PerformanceMeasure, WTFMove(entry));
+        return createWrapper<PerformanceMeasure>(globalObject, WTFMove(entry));
 #endif
 
-    return createWrapper<JSPerformanceEntry>(globalObject, WTFMove(entry));
+    return createWrapper<PerformanceEntry>(globalObject, WTFMove(entry));
 }
 
 JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, PerformanceEntry& entry)
@@ -69,4 +69,5 @@
 }
 
 } // namespace WebCore
+
 #endif // ENABLE(WEB_TIMING)
diff --git a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
index 7616c32..b474718 100644
--- a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
+++ b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
@@ -63,46 +63,46 @@
 {
     switch (object->pathSegType()) {
     case SVGPathSeg::PATHSEG_CLOSEPATH:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegClosePath, WTFMove(object));
+        return createWrapper<SVGPathSegClosePath>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_MOVETO_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegMovetoAbs, WTFMove(object));
+        return createWrapper<SVGPathSegMovetoAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_MOVETO_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegMovetoRel, WTFMove(object));
+        return createWrapper<SVGPathSegMovetoRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_LINETO_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegLinetoAbs, WTFMove(object));
+        return createWrapper<SVGPathSegLinetoAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_LINETO_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegLinetoRel, WTFMove(object));
+        return createWrapper<SVGPathSegLinetoRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoCubicAbs, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoCubicAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoCubicRel, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoCubicRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoQuadraticAbs, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoQuadraticAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoQuadraticRel, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoQuadraticRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_ARC_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegArcAbs, WTFMove(object));
+        return createWrapper<SVGPathSegArcAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_ARC_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegArcRel, WTFMove(object));
+        return createWrapper<SVGPathSegArcRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegLinetoHorizontalAbs, WTFMove(object));
+        return createWrapper<SVGPathSegLinetoHorizontalAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegLinetoHorizontalRel, WTFMove(object));
+        return createWrapper<SVGPathSegLinetoHorizontalRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegLinetoVerticalAbs, WTFMove(object));
+        return createWrapper<SVGPathSegLinetoVerticalAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegLinetoVerticalRel, WTFMove(object));
+        return createWrapper<SVGPathSegLinetoVerticalRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoCubicSmoothAbs, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoCubicSmoothAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoCubicSmoothRel, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoCubicSmoothRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoQuadraticSmoothAbs, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoQuadraticSmoothAbs>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSegCurvetoQuadraticSmoothRel, WTFMove(object));
+        return createWrapper<SVGPathSegCurvetoQuadraticSmoothRel>(globalObject, WTFMove(object));
     case SVGPathSeg::PATHSEG_UNKNOWN:
     default:
-        return CREATE_DOM_WRAPPER(globalObject, SVGPathSeg, WTFMove(object));
+        return createWrapper<SVGPathSeg>(globalObject, WTFMove(object));
     }
 }
 
diff --git a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
index f51331b..5c3b82f 100644
--- a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
+++ b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
@@ -38,8 +38,8 @@
 JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<StyleSheet>&& styleSheet)
 {
     if (styleSheet->isCSSStyleSheet())
-        return CREATE_DOM_WRAPPER(globalObject, CSSStyleSheet, WTFMove(styleSheet));
-    return CREATE_DOM_WRAPPER(globalObject, StyleSheet, WTFMove(styleSheet));
+        return createWrapper<CSSStyleSheet>(globalObject, WTFMove(styleSheet));
+    return createWrapper<StyleSheet>(globalObject, WTFMove(styleSheet));
 }
 
 JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, StyleSheet& stylesheet)
diff --git a/Source/WebCore/bindings/js/JSTextCustom.cpp b/Source/WebCore/bindings/js/JSTextCustom.cpp
index 23320f8..8343e50 100644
--- a/Source/WebCore/bindings/js/JSTextCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTextCustom.cpp
@@ -35,8 +35,8 @@
 JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Text>&& text)
 {
     if (is<CDATASection>(text.get()))
-        return CREATE_DOM_WRAPPER(globalObject, CDATASection, WTFMove(text));
-    return CREATE_DOM_WRAPPER(globalObject, Text, WTFMove(text));
+        return createWrapper<CDATASection>(globalObject, WTFMove(text));
+    return createWrapper<Text>(globalObject, WTFMove(text));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Text& text)
diff --git a/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp b/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp
index e349b4a..24b8fc3 100644
--- a/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp
@@ -64,10 +64,10 @@
     // This switch will make more sense once we support DataCue
     switch (cue->cueType()) {
     case TextTrackCue::Data:
-        return CREATE_DOM_WRAPPER(globalObject, DataCue, WTFMove(cue));
+        return createWrapper<DataCue>(globalObject, WTFMove(cue));
     case TextTrackCue::WebVTT:
     case TextTrackCue::Generic:
-        return CREATE_DOM_WRAPPER(globalObject, VTTCue, WTFMove(cue));
+        return createWrapper<VTTCue>(globalObject, WTFMove(cue));
     default:
         ASSERT_NOT_REACHED();
         return jsNull();
diff --git a/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp b/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp
index 655e35c..c89069e 100644
--- a/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp
+++ b/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp
@@ -120,9 +120,9 @@
 {
 #if ENABLE(WEBGL2)
     if (is<WebGL2RenderingContext>(object))
-        return CREATE_DOM_WRAPPER(globalObject, WebGL2RenderingContext, WTFMove(object));
+        return createWrapper<WebGL2RenderingContext>(globalObject, WTFMove(object));
 #endif
-    return CREATE_DOM_WRAPPER(globalObject, WebGLRenderingContext, WTFMove(object));
+    return createWrapper<WebGLRenderingContext>(globalObject, WTFMove(object));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, WebGLRenderingContextBase& object)
diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
index b893010..b6c09ee 100644
--- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
+++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
@@ -28,6 +28,7 @@
 #define JSWorkerGlobalScopeBase_h
 
 #include "JSDOMGlobalObject.h"
+#include "JSDOMWrapper.h"
 
 namespace WebCore {
 
diff --git a/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp b/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp
index f0188d0..9c82c50 100644
--- a/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp
@@ -35,11 +35,11 @@
 
 using namespace JSC;
 
-JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<XMLDocument>&& passedDocument)
+JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<XMLDocument>&& document)
 {
-    reportMemoryForDocumentIfFrameless(*state, passedDocument.get());
+    reportMemoryForDocumentIfFrameless(*state, document.get());
 
-    return CREATE_DOM_WRAPPER(globalObject, XMLDocument, WTFMove(passedDocument));
+    return createWrapper<XMLDocument>(globalObject, WTFMove(document));
 }
 
 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, XMLDocument& document)
diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
index 616bab1..b5c6e48 100644
--- a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -1582,6 +1582,12 @@
         push(@headerContent, "bool fill${interfaceName}Init(${interfaceName}Init&, JSDictionary&);\n\n");
     }
 
+    if (NeedsImplementationClass($interface)) {
+        push(@headerContent, "template<> struct JSDOMWrapperConverterTraits<${implType}> {\n");
+        push(@headerContent, "    using WrapperClass = ${className};\n");
+        push(@headerContent, "};\n");
+    }
+
     my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
     push(@headerContent, "\n} // namespace WebCore\n");
     push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
@@ -3708,7 +3714,7 @@
     globalObject->vm().heap.reportExtraMemoryAllocated(impl->memoryCost());
 END
 
-        push(@implContent, "    return createWrapper<$className, $implType>(globalObject, WTFMove(impl));\n");
+        push(@implContent, "    return createWrapper<$implType>(globalObject, WTFMove(impl));\n");
         push(@implContent, "}\n\n");
 
         push(@implContent, "JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, $implType& impl)\n");
@@ -5298,7 +5304,7 @@
     }
 
     Ref<${interfaceName}> event = ${interfaceName}::createForBindings(eventType, eventInit);
-    return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), ${interfaceName}, WTFMove(event)));
+    return JSValue::encode(createWrapper<${interfaceName}>(jsConstructor->globalObject(), WTFMove(event)));
 }
 
 bool fill${interfaceName}Init(${interfaceName}Init& eventInit, JSDictionary& dictionary)