Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (284240 => 284241)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2021-10-15 10:24:43 UTC (rev 284241)
@@ -1,3 +1,17 @@
+2021-10-15 Alexey Shvayka <shvaikal...@gmail.com>
+
+ [WebIDL] JSDOMBuiltinConstructor instances should support subclassing
+ https://bugs.webkit.org/show_bug.cgi?id=231689
+
+ Reviewed by Youenn Fablet.
+
+ * web-platform-tests/streams/queuing-strategies.any-expected.txt:
+ * web-platform-tests/streams/queuing-strategies.any.worker-expected.txt:
+ * web-platform-tests/streams/readable-streams/general.any-expected.txt:
+ * web-platform-tests/streams/readable-streams/general.any.worker-expected.txt:
+ * web-platform-tests/streams/transform-streams/general.any-expected.txt:
+ * web-platform-tests/streams/transform-streams/general.any.worker-expected.txt:
+
2021-10-14 Antti Koivisto <an...@apple.com>
[CSS Cascade Layers] Layer should have higher priority than its descendant layers
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/queuing-strategies.any-expected.txt (284240 => 284241)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/queuing-strategies.any-expected.txt 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/queuing-strategies.any-expected.txt 2021-10-15 10:24:43 UTC (rev 284241)
@@ -4,13 +4,13 @@
PASS CountQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules
PASS CountQueuingStrategy: size is the same function across all instances
PASS CountQueuingStrategy: size should have the right name
-FAIL CountQueuingStrategy: subclassing should work correctly assert_equals: constructor.name should be correct expected "SubClass" but got "CountQueuingStrategy"
+PASS CountQueuingStrategy: subclassing should work correctly
PASS ByteLengthQueuingStrategy: Can construct a with a valid high water mark
PASS ByteLengthQueuingStrategy: Constructor behaves as expected with strange arguments
PASS ByteLengthQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules
PASS ByteLengthQueuingStrategy: size is the same function across all instances
PASS ByteLengthQueuingStrategy: size should have the right name
-FAIL ByteLengthQueuingStrategy: subclassing should work correctly assert_equals: constructor.name should be correct expected "SubClass" but got "ByteLengthQueuingStrategy"
+PASS ByteLengthQueuingStrategy: subclassing should work correctly
PASS CountQueuingStrategy: size should have the right length
PASS ByteLengthQueuingStrategy: size should have the right length
PASS CountQueuingStrategy: size behaves as expected with strange arguments
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/queuing-strategies.any.worker-expected.txt (284240 => 284241)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/queuing-strategies.any.worker-expected.txt 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/queuing-strategies.any.worker-expected.txt 2021-10-15 10:24:43 UTC (rev 284241)
@@ -4,13 +4,13 @@
PASS CountQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules
PASS CountQueuingStrategy: size is the same function across all instances
PASS CountQueuingStrategy: size should have the right name
-FAIL CountQueuingStrategy: subclassing should work correctly assert_equals: constructor.name should be correct expected "SubClass" but got "CountQueuingStrategy"
+PASS CountQueuingStrategy: subclassing should work correctly
PASS ByteLengthQueuingStrategy: Can construct a with a valid high water mark
PASS ByteLengthQueuingStrategy: Constructor behaves as expected with strange arguments
PASS ByteLengthQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules
PASS ByteLengthQueuingStrategy: size is the same function across all instances
PASS ByteLengthQueuingStrategy: size should have the right name
-FAIL ByteLengthQueuingStrategy: subclassing should work correctly assert_equals: constructor.name should be correct expected "SubClass" but got "ByteLengthQueuingStrategy"
+PASS ByteLengthQueuingStrategy: subclassing should work correctly
PASS CountQueuingStrategy: size should have the right length
PASS ByteLengthQueuingStrategy: size should have the right length
PASS CountQueuingStrategy: size behaves as expected with strange arguments
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-streams/general.any-expected.txt (284240 => 284241)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-streams/general.any-expected.txt 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-streams/general.any-expected.txt 2021-10-15 10:24:43 UTC (rev 284241)
@@ -33,7 +33,7 @@
PASS ReadableStream: should call underlying source methods as methods
PASS ReadableStream: desiredSize when closed
PASS ReadableStream: desiredSize when errored
-FAIL Subclassing ReadableStream should work assert_true: Subclass object should be an instance of Subclass expected true got false
+PASS Subclassing ReadableStream should work
PASS ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue
PASS ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately
PASS ReadableStream integration test: adapting a random push source
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-streams/general.any.worker-expected.txt (284240 => 284241)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-streams/general.any.worker-expected.txt 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-streams/general.any.worker-expected.txt 2021-10-15 10:24:43 UTC (rev 284241)
@@ -33,7 +33,7 @@
PASS ReadableStream: should call underlying source methods as methods
PASS ReadableStream: desiredSize when closed
PASS ReadableStream: desiredSize when errored
-FAIL Subclassing ReadableStream should work assert_true: Subclass object should be an instance of Subclass expected true got false
+PASS Subclassing ReadableStream should work
PASS ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue
PASS ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately
PASS ReadableStream integration test: adapting a random push source
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/transform-streams/general.any-expected.txt (284240 => 284241)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/transform-streams/general.any-expected.txt 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/transform-streams/general.any-expected.txt 2021-10-15 10:24:43 UTC (rev 284241)
@@ -23,5 +23,5 @@
PASS start() should not be called twice
PASS specifying a defined readableType should throw
PASS specifying a defined writableType should throw
-FAIL Subclassing TransformStream should work assert_true: Subclass object should be an instance of Subclass expected true got false
+PASS Subclassing TransformStream should work
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/transform-streams/general.any.worker-expected.txt (284240 => 284241)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/transform-streams/general.any.worker-expected.txt 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/transform-streams/general.any.worker-expected.txt 2021-10-15 10:24:43 UTC (rev 284241)
@@ -23,5 +23,5 @@
PASS start() should not be called twice
PASS specifying a defined readableType should throw
PASS specifying a defined writableType should throw
-FAIL Subclassing TransformStream should work assert_true: Subclass object should be an instance of Subclass expected true got false
+PASS Subclassing TransformStream should work
Modified: trunk/Source/WebCore/ChangeLog (284240 => 284241)
--- trunk/Source/WebCore/ChangeLog 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/Source/WebCore/ChangeLog 2021-10-15 10:24:43 UTC (rev 284241)
@@ -1,3 +1,47 @@
+2021-10-15 Alexey Shvayka <shvaikal...@gmail.com>
+
+ [WebIDL] JSDOMBuiltinConstructor instances should support subclassing
+ https://bugs.webkit.org/show_bug.cgi?id=231689
+
+ Reviewed by Youenn Fablet.
+
+ This patch:
+
+ 1. Removes JSDOMObjectInspector and related conditional createJSObject() / callConstructor()
+ overloads: they aren't necessary because code generator guarantees that built-in constructors
+ are called only on JSDOMObjectInspector<JSClass>::isBuiltin objects.
+
+ 2. Implements proper subclassing [1] for built-in constructors, ensuring exception checking
+ and rare cases are kept off the fast path. For simplicity and consistency with JSC built-ins
+ and setSubclassStructureIfNeeded(), getFunctionRealm() is called before "prototype" lookup,
+ which is non-observable.
+
+ 3. Further improves constructor's fast path by replacing slowish argument-copying
+ callFunctionWithCurrentArguments() with ArgList(CallFrame*) constructor.
+
+ [1] https://webidl.spec.whatwg.org/#internally-create-a-new-object-implementing-the-interface (step 3)
+
+ Tests: imported/w3c/web-platform-tests/streams/queuing-strategies.any.js
+ imported/w3c/web-platform-tests/streams/readable-streams/general.any.js
+ imported/w3c/web-platform-tests/streams/transform-streams/general.any.js
+
+ * bindings/js/JSDOMBuiltinConstructor.h:
+ (WebCore::JSDOMBuiltinConstructor<JSClass>::getDOMStructureForJSObject):
+ (WebCore::JSDOMBuiltinConstructor<JSClass>::construct):
+ (WebCore::JSDOMBuiltinConstructor<JSClass>::callConstructor): Deleted.
+ (WebCore::createJSObject): Deleted.
+ * bindings/js/JSDOMBuiltinConstructorBase.cpp:
+ (WebCore::JSDOMBuiltinConstructorBase::callFunctionWithCurrentArguments): Deleted.
+ * bindings/js/JSDOMBuiltinConstructorBase.h:
+ * bindings/js/JSDOMWrapper.h:
+ * bindings/scripts/CodeGeneratorJS.pm:
+ (AddJSBuiltinIncludesIfNeeded):
+ Removes [JSBuiltin] check because it's superseded by HasJSBuiltinConstructor helper.
+
+ * bindings/scripts/IDLAttributes.json:
+ Removes unused [JSBuiltinConstructor] extended attribute:
+ [JSBuiltin] on constructor() or interface should be used instead.
+
2021-10-15 Michael Catanzaro <mcatanz...@gnome.org>
[WPE][GTK] Update user agent browser versions
Modified: trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h (284240 => 284241)
--- trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h 2021-10-15 10:24:43 UTC (rev 284241)
@@ -47,8 +47,7 @@
void finishCreation(JSC::VM&, JSDOMGlobalObject&);
- JSC::EncodedJSValue callConstructor(JSC::JSGlobalObject&, JSC::CallFrame&, JSC::JSObject&);
- JSC::EncodedJSValue callConstructor(JSC::JSGlobalObject&, JSC::CallFrame&, JSC::JSObject*);
+ JSC::Structure* getDOMStructureForJSObject(JSC::JSGlobalObject*, JSC::JSObject* newTarget);
// Usually defined for each specialization class.
void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { }
@@ -76,46 +75,31 @@
initializeProperties(vm, globalObject);
}
-template<typename JSClass> inline JSC::EncodedJSValue JSDOMBuiltinConstructor<JSClass>::callConstructor(JSC::JSGlobalObject& lexicalGlobalObject, JSC::CallFrame& callFrame, JSC::JSObject& object)
+template<typename JSClass> inline JSC::Structure* JSDOMBuiltinConstructor<JSClass>::getDOMStructureForJSObject(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* newTarget)
{
- Base::callFunctionWithCurrentArguments(lexicalGlobalObject, callFrame, object, *initializeFunction());
- return JSC::JSValue::encode(&object);
-}
+ auto& vm = JSC::getVM(lexicalGlobalObject);
-template<typename JSClass> inline JSC::EncodedJSValue JSDOMBuiltinConstructor<JSClass>::callConstructor(JSC::JSGlobalObject& lexicalGlobalObject, JSC::CallFrame& callFrame, JSC::JSObject* object)
-{
- JSC::VM& vm = JSC::getVM(&lexicalGlobalObject);
+ if (LIKELY(newTarget == this))
+ return getDOMStructure<JSClass>(vm, *globalObject());
+
auto scope = DECLARE_THROW_SCOPE(vm);
- if (!object)
- return throwConstructorScriptExecutionContextUnavailableError(lexicalGlobalObject, scope, info()->className);
- return callConstructor(lexicalGlobalObject, callFrame, *object);
+ auto* newTargetGlobalObject = JSC::getFunctionRealm(lexicalGlobalObject, newTarget);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ auto* baseStructure = getDOMStructure<JSClass>(vm, *JSC::jsCast<JSDOMGlobalObject*>(newTargetGlobalObject));
+ RELEASE_AND_RETURN(scope, JSC::InternalFunction::createSubclassStructure(lexicalGlobalObject, newTarget, baseStructure));
}
-template<typename JSClass>
-typename std::enable_if<JSDOMObjectInspector<JSClass>::isSimpleWrapper, JSC::JSObject&>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor)
-{
- return *createWrapper<typename JSClass::DOMWrapped>(constructor.globalObject(), JSClass::DOMWrapped::create());
-}
-
-template<typename JSClass>
-typename std::enable_if<JSDOMObjectInspector<JSClass>::isBuiltin, JSC::JSObject&>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor)
-{
- auto& globalObject = *constructor.globalObject();
- return *JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject);
-}
-
-template<typename JSClass>
-typename std::enable_if<JSDOMObjectInspector<JSClass>::isComplexWrapper, JSC::JSObject*>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor)
-{
- auto* context = constructor.scriptExecutionContext();
- return context ? createWrapper<typename JSClass::DOMWrapped>(constructor.globalObject(), JSClass::DOMWrapped::create(*context)) : nullptr;
-}
-
template<typename JSClass> inline JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMBuiltinConstructor<JSClass>::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
{
ASSERT(callFrame);
auto* castedThis = JSC::jsCast<JSDOMBuiltinConstructor*>(callFrame->jsCallee());
- return castedThis->callConstructor(*lexicalGlobalObject, *callFrame, createJSObject(*castedThis));
+ auto* structure = castedThis->getDOMStructureForJSObject(lexicalGlobalObject, asObject(callFrame->newTarget()));
+ if (UNLIKELY(!structure))
+ return { };
+
+ auto* jsObject = JSClass::create(structure, castedThis->globalObject());
+ JSC::call(lexicalGlobalObject, castedThis->initializeFunction(), jsObject, JSC::ArgList(callFrame), "This error should never occur: initialize function is guaranteed to be callable.");
+ return JSC::JSValue::encode(jsObject);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp (284240 => 284241)
--- trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp 2021-10-15 10:24:43 UTC (rev 284241)
@@ -27,25 +27,7 @@
namespace WebCore {
using namespace JSC;
-
-void JSDOMBuiltinConstructorBase::callFunctionWithCurrentArguments(JSC::JSGlobalObject& lexicalGlobalObject, JSC::CallFrame& callFrame, JSC::JSObject& thisObject, JSC::JSFunction& function)
-{
- JSC::VM& vm = lexicalGlobalObject.vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
- auto callData = JSC::getCallData(vm, &function);
- ASSERT(callData.type != CallData::Type::None);
- JSC::MarkedArgumentBuffer arguments;
- for (unsigned i = 0; i < callFrame.argumentCount(); ++i)
- arguments.append(callFrame.uncheckedArgument(i));
- if (UNLIKELY(arguments.hasOverflowed())) {
- throwOutOfMemoryError(&lexicalGlobalObject, scope);
- return;
- }
- scope.release();
- JSC::call(&lexicalGlobalObject, &function, callData, &thisObject, arguments);
-}
-
template<typename Visitor>
void JSDOMBuiltinConstructorBase::visitChildrenImpl(JSC::JSCell* cell, Visitor& visitor)
{
Modified: trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h (284240 => 284241)
--- trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h 2021-10-15 10:24:43 UTC (rev 284241)
@@ -47,8 +47,6 @@
JSC::JSFunction* initializeFunction();
void setInitializeFunction(JSC::VM&, JSC::JSFunction&);
- static void callFunctionWithCurrentArguments(JSC::JSGlobalObject&, JSC::CallFrame&, JSC::JSObject& thisObject, JSC::JSFunction&);
-
private:
static JSC::IsoSubspace* subspaceForImpl(JSC::VM&);
Modified: trunk/Source/WebCore/bindings/js/JSDOMWrapper.h (284240 => 284241)
--- trunk/Source/WebCore/bindings/js/JSDOMWrapper.h 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/Source/WebCore/bindings/js/JSDOMWrapper.h 2021-10-15 10:24:43 UTC (rev 284241)
@@ -57,7 +57,6 @@
class JSDOMObject : public JSC::JSDestructibleObject {
public:
typedef JSC::JSDestructibleObject Base;
- static constexpr bool isDOMWrapper = false;
template<typename, JSC::SubspaceAccess>
static void subspaceFor(JSC::VM&) { RELEASE_ASSERT_NOT_REACHED(); }
@@ -73,7 +72,6 @@
public:
typedef JSDOMObject Base;
typedef ImplementationClass DOMWrapped;
- static constexpr bool isDOMWrapper = true;
ImplementationClass& wrapped() const { return m_wrapped; }
static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper<ImplementationClass>, m_wrapped); }
@@ -89,26 +87,6 @@
template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;
-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;
-};
-
JSC::JSValue cloneAcrossWorlds(JSC::JSGlobalObject&, const JSDOMObject& owner, JSC::JSValue);
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (284240 => 284241)
--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2021-10-15 10:24:43 UTC (rev 284241)
@@ -8016,7 +8016,7 @@
{
my $interface = shift;
- if ($interface->extendedAttributes->{JSBuiltin} || HasJSBuiltinConstructor($interface)) {
+ if (HasJSBuiltinConstructor($interface)) {
AddToImplIncludes($interface->type->name . "Builtins.h");
return;
}
Modified: trunk/Source/WebCore/bindings/scripts/IDLAttributes.json (284240 => 284241)
--- trunk/Source/WebCore/bindings/scripts/IDLAttributes.json 2021-10-15 09:26:08 UTC (rev 284240)
+++ trunk/Source/WebCore/bindings/scripts/IDLAttributes.json 2021-10-15 10:24:43 UTC (rev 284241)
@@ -268,9 +268,6 @@
"JSBuiltin": {
"contextsAllowed": ["interface", "attribute", "operation"]
},
- "JSBuiltinConstructor": {
- "contextsAllowed": ["interface"]
- },
"JSCustomFinalize": {
"contextsAllowed": ["interface"]
},