Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Enable DOM class create functions to take parameters in case of JSBui…
…ltinConstructor

https://bugs.webkit.org/show_bug.cgi?id=155022

Reviewed by Darin Adler.

Introducing JSDOMObjectInspector to check whether a given JS class is built-in (no DOM class).
If that is not the case, the JS class wraps a DOM class.
The inspector detects whether the DOM class create static method takes no parameter or some parameters.
This is used in JSDOMConstructor.h to generate correctly the createJSObject functions needed by JSBuiltinConstructor.

Updated binding generator to not generate anymore createJSObject as it is handled directly in JSDOMConstructor.h.

Covered by existing tests.

* bindings/js/JSDOMConstructor.h:
(WebCore::JSBuiltinConstructor<JSClass>::callConstructor):
(WebCore::createJSObject):
(WebCore::JSBuiltinConstructor<JSClass>::construct):
* bindings/js/JSDOMWrapper.h:
* bindings/js/JSKeyValueIterator.h: Taking benefit of JSClass::DOMWrapper type declaration.
* bindings/js/JSReadableStreamPrivateConstructors.cpp:
(WebCore::JSBuiltinReadableStreamReaderPrivateConstructor::initializeExecutable): Deleted.
(WebCore::JSBuiltinReadableStreamControllerPrivateConstructor::initializeExecutable): Deleted.
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateConstructorDefinition): Deleted.
* bindings/scripts/test/JS/JSTestClassWithJSBuiltinConstructor.cpp:
(WebCore::JSTestClassWithJSBuiltinConstructorConstructor::prototypeForStructure): Deleted.


Canonical link: https://commits.webkit.org/173176@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@197642 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
youennf committed Mar 6, 2016
1 parent ebd944c commit f37bd74
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 36 deletions.
30 changes: 30 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,33 @@
2016-03-06 Youenn Fablet <youenn.fablet@crf.canon.fr>

Enable DOM class create functions to take parameters in case of JSBuiltinConstructor
https://bugs.webkit.org/show_bug.cgi?id=155022

Reviewed by Darin Adler.

Introducing JSDOMObjectInspector to check whether a given JS class is built-in (no DOM class).
If that is not the case, the JS class wraps a DOM class.
The inspector detects whether the DOM class create static method takes no parameter or some parameters.
This is used in JSDOMConstructor.h to generate correctly the createJSObject functions needed by JSBuiltinConstructor.

Updated binding generator to not generate anymore createJSObject as it is handled directly in JSDOMConstructor.h.

Covered by existing tests.

* bindings/js/JSDOMConstructor.h:
(WebCore::JSBuiltinConstructor<JSClass>::callConstructor):
(WebCore::createJSObject):
(WebCore::JSBuiltinConstructor<JSClass>::construct):
* bindings/js/JSDOMWrapper.h:
* bindings/js/JSKeyValueIterator.h: Taking benefit of JSClass::DOMWrapper type declaration.
* bindings/js/JSReadableStreamPrivateConstructors.cpp:
(WebCore::JSBuiltinReadableStreamReaderPrivateConstructor::initializeExecutable): Deleted.
(WebCore::JSBuiltinReadableStreamControllerPrivateConstructor::initializeExecutable): Deleted.
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateConstructorDefinition): Deleted.
* bindings/scripts/test/JS/JSTestClassWithJSBuiltinConstructor.cpp:
(WebCore::JSTestClassWithJSBuiltinConstructorConstructor::prototypeForStructure): Deleted.

2016-03-06 Antti Koivisto <antti@apple.com>

RenderTextControlSingleLine shouldn't mutate placeholder element inline style
Expand Down
51 changes: 42 additions & 9 deletions Source/WebCore/bindings/js/JSDOMConstructor.h
Expand Up @@ -104,7 +104,7 @@ template<typename JSClass> class JSDOMNamedConstructor : public DOMConstructorWi

template<typename JSClass> class JSBuiltinConstructor : public DOMConstructorJSBuiltinObject {
public:
typedef DOMConstructorJSBuiltinObject Base;
using Base = DOMConstructorJSBuiltinObject;

static JSBuiltinConstructor* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&);
static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype);
Expand All @@ -119,7 +119,9 @@ template<typename JSClass> class JSBuiltinConstructor : public DOMConstructorJSB
void finishCreation(JSC::VM&, JSDOMGlobalObject&);
static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);
static JSC::EncodedJSValue JSC_HOST_CALL construct(JSC::ExecState*);
JSC::JSObject* createJSObject();

JSC::EncodedJSValue callConstructor(JSC::ExecState&, JSC::JSObject&);
JSC::EncodedJSValue callConstructor(JSC::ExecState&, JSC::JSObject*);

// Usually defined for each specialization class.
void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { }
Expand Down Expand Up @@ -216,17 +218,48 @@ template<typename JSClass> inline void JSBuiltinConstructor<JSClass>::finishCrea
initializeProperties(vm, globalObject);
}

template<typename JSClass> inline JSC::EncodedJSValue JSC_HOST_CALL JSBuiltinConstructor<JSClass>::construct(JSC::ExecState* state)
template<typename JSClass> inline JSC::EncodedJSValue JSBuiltinConstructor<JSClass>::callConstructor(JSC::ExecState& state, JSC::JSObject& object)
{
auto* castedThis = JSC::jsCast<JSBuiltinConstructor*>(state->callee());
auto* object = castedThis->createJSObject();
callFunctionWithCurrentArguments(*state, *object, *castedThis->initializeFunction());
return JSC::JSValue::encode(object);
callFunctionWithCurrentArguments(state, object, *initializeFunction());
return JSC::JSValue::encode(&object);
}

template<typename JSClass> inline JSC::EncodedJSValue JSBuiltinConstructor<JSClass>::callConstructor(JSC::ExecState& state, JSC::JSObject* object)
{
if (!object)
return throwConstructorDocumentUnavailableError(state, info()->className);
return callConstructor(state, *object);
}

template<typename JSClass> inline
typename std::enable_if<JSDOMObjectInspector<JSClass>::isSimpleWrapper, JSC::JSObject&>::type createJSObject(JSBuiltinConstructor<JSClass>& constructor)
{
auto& globalObject = *constructor.globalObject();
return *JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject, JSClass::DOMWrapped::create());
}

template<typename JSClass> inline JSC::JSObject* JSBuiltinConstructor<JSClass>::createJSObject()
template<typename JSClass> inline
typename std::enable_if<JSDOMObjectInspector<JSClass>::isBuiltin, JSC::JSObject&>::type createJSObject(JSBuiltinConstructor<JSClass>& constructor)
{
return JSClass::create(getDOMStructure<JSClass>(globalObject()->vm(), *globalObject()), globalObject());
auto& globalObject = *constructor.globalObject();
return *JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject);
}

template<typename JSClass> inline
typename std::enable_if<JSDOMObjectInspector<JSClass>::isComplexWrapper, JSC::JSObject*>::type createJSObject(JSBuiltinConstructor<JSClass>& constructor)
{
ScriptExecutionContext* context = constructor.scriptExecutionContext();
if (!context)
return nullptr;
auto& globalObject = *constructor.globalObject();
return JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject, JSClass::DOMWrapped::create(*context));
}

template<typename JSClass> inline JSC::EncodedJSValue JSC_HOST_CALL JSBuiltinConstructor<JSClass>::construct(JSC::ExecState* state)
{
ASSERT(state);
auto* castedThis = JSC::jsCast<JSBuiltinConstructor*>(state->callee());
return castedThis->callConstructor(*state, createJSObject(*castedThis));
}

template<typename JSClass> inline JSC::ConstructType JSBuiltinConstructor<JSClass>::getConstructData(JSC::JSCell*, JSC::ConstructData& constructData)
Expand Down
23 changes: 23 additions & 0 deletions Source/WebCore/bindings/js/JSDOMWrapper.h
Expand Up @@ -36,6 +36,7 @@ static const uint8_t JSElementType = JSC::LastJSCObjectType + 3;
class JSDOMObject : public JSC::JSDestructibleObject {
public:
typedef JSC::JSDestructibleObject Base;
static constexpr bool isDOMWrapper = false;

JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(JSC::JSNonFinalObject::globalObject()); }
ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); }
Expand All @@ -51,6 +52,8 @@ class JSDOMObject : public JSC::JSDestructibleObject {
template<typename ImplementationClass> class JSDOMWrapper : public JSDOMObject {
public:
typedef JSDOMObject Base;
typedef ImplementationClass DOMWrapped;
static constexpr bool isDOMWrapper = true;

ImplementationClass& wrapped() const { return const_cast<ImplementationClass&>(m_wrapped.get()); }

Expand All @@ -63,6 +66,26 @@ template<typename ImplementationClass> class JSDOMWrapper : public JSDOMObject {
Ref<ImplementationClass> m_wrapped;
};

template<typename JSClass, typename Enable = void>
struct JSDOMObjectInspector {
public:
static constexpr bool isSimpleWrapper = false;
static constexpr bool isComplexWrapper = false;
static constexpr bool isBuiltin = true;
};

template<typename JSClass>
struct JSDOMObjectInspector<JSClass, typename std::enable_if<JSClass::isDOMWrapper>::type> {
private:
template<typename T> static constexpr auto test(int) -> decltype(T::create(), bool()) { return true; }
template<typename T> static constexpr bool test(...) { return false; }

public:
static constexpr bool isSimpleWrapper = test<typename JSClass::DOMWrapped>(0);
static constexpr bool isComplexWrapper = !isSimpleWrapper;
static constexpr bool isBuiltin = false;
};

} // namespace WebCore

#endif // JSDOMWrapper_h
2 changes: 1 addition & 1 deletion Source/WebCore/bindings/js/JSKeyValueIterator.h
Expand Up @@ -35,8 +35,8 @@ namespace WebCore {
template<typename JSWrapper>
class JSKeyValueIteratorPrototype : public JSC::JSNonFinalObject {
public:
using DOMWrapped = typename std::remove_reference<decltype(std::declval<JSWrapper>().wrapped())>::type;
using Base = JSC::JSNonFinalObject;
using DOMWrapped = typename JSWrapper::DOMWrapped;

static JSKeyValueIteratorPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
{
Expand Down
10 changes: 0 additions & 10 deletions Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp
Expand Up @@ -63,16 +63,6 @@ STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSBuiltinReadableStreamControllerPrivate
template<> const ClassInfo JSBuiltinReadableStreamReaderPrivateConstructor::s_info = { "ReadableStreamReaderPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableStreamReaderPrivateConstructor) };
template<> const ClassInfo JSBuiltinReadableStreamControllerPrivateConstructor::s_info = { "ReadableStreamControllerPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableStreamControllerPrivateConstructor) };

template<> JSObject* JSBuiltinReadableStreamReaderPrivateConstructor::createJSObject()
{
return JSReadableStreamReader::create(getDOMStructure<JSReadableStreamReader>(globalObject()->vm(), *globalObject()), globalObject());
}

template<> JSObject* JSBuiltinReadableStreamControllerPrivateConstructor::createJSObject()
{
return JSReadableStreamController::create(getDOMStructure<JSReadableStreamController>(globalObject()->vm(), *globalObject()), globalObject());
}

template<> FunctionExecutable* JSBuiltinReadableStreamReaderPrivateConstructor::initializeExecutable(JSC::VM& vm)
{
return readableStreamInternalsPrivateInitializeReadableStreamReaderCodeGenerator(vm);
Expand Down
11 changes: 0 additions & 11 deletions Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Expand Up @@ -4788,18 +4788,7 @@ sub GenerateConstructorDefinition
my $generatingNamedConstructor = shift;
my $function = shift;


if (IsJSBuiltinConstructor($interface)) {
if ($interface->extendedAttributes->{"JSBuiltinConstructor"}) {
# FIXME: Add support for ConstructorCallWith
push(@$outputArray, <<END);
template<> JSC::JSObject* ${className}Constructor::createJSObject()
{
return ${className}::create(getDOMStructure<${className}>(globalObject()->vm(), *globalObject()), globalObject(), ${interfaceName}::create());
}
END
}
return;
}

Expand Down
Expand Up @@ -63,11 +63,6 @@ class JSTestClassWithJSBuiltinConstructorPrototype : public JSC::JSNonFinalObjec

typedef JSBuiltinConstructor<JSTestClassWithJSBuiltinConstructor> JSTestClassWithJSBuiltinConstructorConstructor;

template<> JSC::JSObject* JSTestClassWithJSBuiltinConstructorConstructor::createJSObject()
{
return JSTestClassWithJSBuiltinConstructor::create(getDOMStructure<JSTestClassWithJSBuiltinConstructor>(globalObject()->vm(), *globalObject()), globalObject(), TestClassWithJSBuiltinConstructor::create());
}

template<> JSValue JSTestClassWithJSBuiltinConstructorConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
{
UNUSED_PARAM(vm);
Expand Down

0 comments on commit f37bd74

Please sign in to comment.