Skip to content
Permalink
Browse files
Update CustomEvent to stop using legacy [ConstructorTemplate=Event]
https://bugs.webkit.org/show_bug.cgi?id=163174

Reviewed by Darin Adler.

Source/WebCore:

Update CustomEvent to stop using legacy [ConstructorTemplate=Event] and
use an actual constructor instead, like in the specification:
- https://dom.spec.whatwg.org/#interface-customevent

There is a very minor behavior change when explictly passing undefined
as detail value in CustomEventInit. We used to initialize detail to
undefined but we now initialize it to null instead, which is its default
value. The new behavior matches the one of Chrome and Firefox.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateDefaultValue):
(GenerateDictionaryImplementationContent):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::convertDictionary<TestObj::Dictionary>):
* bindings/scripts/test/TestObj.idl:
* dom/CustomEvent.cpp:
(WebCore::CustomEvent::CustomEvent):
* dom/CustomEvent.h:
* dom/CustomEvent.idl:
* dom/Document.cpp:
(WebCore::Document::createEvent):
* dom/Event.cpp:
(WebCore::Event::Event):
* dom/Event.h:

LayoutTests:

Update existing layout test to reflect minor behavior change.

* fast/events/constructors/custom-event-constructor-expected.txt:
* fast/events/constructors/custom-event-constructor.html:

Canonical link: https://commits.webkit.org/181012@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@206964 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
cdumez committed Oct 9, 2016
1 parent ba6fb49 commit 12d2ab13d1b6fba72c4e5cc9fa13e75f37b31551
@@ -1,3 +1,15 @@
2016-10-08 Chris Dumez <cdumez@apple.com>

Update CustomEvent to stop using legacy [ConstructorTemplate=Event]
https://bugs.webkit.org/show_bug.cgi?id=163174

Reviewed by Darin Adler.

Update existing layout test to reflect minor behavior change.

* fast/events/constructors/custom-event-constructor-expected.txt:
* fast/events/constructors/custom-event-constructor.html:

2016-10-08 Chris Dumez <cdumez@apple.com>

Add support for ClipboardEvent
@@ -13,7 +13,7 @@ PASS new CustomEvent('eventType', { detail: 10 }).detail is 10
PASS new CustomEvent('eventType', { detail: 'string' }).detail is 'string'
PASS new CustomEvent('eventType', { detail: detailObject }).detail is detailObject
PASS new CustomEvent('eventType', { detail: document }).detail is document
PASS new CustomEvent('eventType', { detail: undefined }).detail is undefined
PASS new CustomEvent('eventType', { detail: undefined }).detail is null
PASS new CustomEvent('eventType', { detail: null }).detail is null
PASS new CustomEvent('eventType', { get detail() { return true; } }).detail is true
PASS new CustomEvent('eventType', { get detail() { throw 'Custom Error'; } }) threw exception Custom Error.
@@ -32,10 +32,10 @@
shouldBe("new CustomEvent('eventType', { detail: document }).detail", "document");

// Detail is undefined.
shouldBe("new CustomEvent('eventType', { detail: undefined }).detail", "undefined");
shouldBeNull("new CustomEvent('eventType', { detail: undefined }).detail");

// Detail is null.
shouldBe("new CustomEvent('eventType', { detail: null }).detail", "null");
shouldBeNull("new CustomEvent('eventType', { detail: null }).detail");

// Detail is a getter.
shouldBe("new CustomEvent('eventType', { get detail() { return true; } }).detail", "true");
@@ -1,3 +1,35 @@
2016-10-08 Chris Dumez <cdumez@apple.com>

Update CustomEvent to stop using legacy [ConstructorTemplate=Event]
https://bugs.webkit.org/show_bug.cgi?id=163174

Reviewed by Darin Adler.

Update CustomEvent to stop using legacy [ConstructorTemplate=Event] and
use an actual constructor instead, like in the specification:
- https://dom.spec.whatwg.org/#interface-customevent

There is a very minor behavior change when explictly passing undefined
as detail value in CustomEventInit. We used to initialize detail to
undefined but we now initialize it to null instead, which is its default
value. The new behavior matches the one of Chrome and Firefox.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateDefaultValue):
(GenerateDictionaryImplementationContent):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::convertDictionary<TestObj::Dictionary>):
* bindings/scripts/test/TestObj.idl:
* dom/CustomEvent.cpp:
(WebCore::CustomEvent::CustomEvent):
* dom/CustomEvent.h:
* dom/CustomEvent.idl:
* dom/Document.cpp:
(WebCore::Document::createEvent):
* dom/Event.cpp:
(WebCore::Event::Event):
* dom/Event.h:

2016-10-08 Chris Dumez <cdumez@apple.com>

Add support for ClipboardEvent
@@ -982,7 +982,9 @@ sub GenerateDefaultValue
my $enumerationValueName = GetEnumerationValueName(substr($value, 1, -1));
$value = $className . "::" . $enumerationValueName;
}
$value = "nullptr" if $value eq "null";
if ($value eq "null") {
$value = $member->type eq "any" ? "jsNull()" : "nullptr";
}
$value = "jsUndefined()" if $value eq "undefined";

return $value;
@@ -1089,7 +1091,7 @@ sub GenerateDictionaryImplementationContent
# For each dictionary member member declared on dictionary, in lexicographical order:
my @sortedMembers = sort { $a->name cmp $b->name } @{$dictionary->members};
foreach my $member (@sortedMembers) {
$member->default("undefined") if $member->type eq "any"; # Use undefined as default value for member of type 'any'.
$member->default("undefined") if $member->type eq "any" and !defined($member->default); # Use undefined as default value for member of type 'any' unless specified otherwise.

my $type = $member->type;

@@ -488,6 +488,13 @@ template<> Optional<TestObj::Dictionary> convertDictionary<TestObj::Dictionary>(
RETURN_IF_EXCEPTION(throwScope, Nullopt);
} else
anyValue = jsUndefined();
JSValue anyValueWithNullDefaultValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "anyValueWithNullDefault"));
JSC::JSValue anyValueWithNullDefault;
if (!anyValueWithNullDefaultValue.isUndefined()) {
anyValueWithNullDefault = convert<JSC::JSValue>(state, anyValueWithNullDefaultValue);
RETURN_IF_EXCEPTION(throwScope, Nullopt);
} else
anyValueWithNullDefault = jsNull();
JSValue booleanWithDefaultValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "booleanWithDefault"));
bool booleanWithDefault;
if (!booleanWithDefaultValue.isUndefined()) {
@@ -682,7 +689,7 @@ template<> Optional<TestObj::Dictionary> convertDictionary<TestObj::Dictionary>(
RETURN_IF_EXCEPTION(throwScope, Nullopt);
} else
unsignedLargeIntegerWithDefault = 0;
return TestObj::Dictionary { WTFMove(enumerationValueWithoutDefault), WTFMove(enumerationValueWithDefault), WTFMove(enumerationValueWithEmptyStringDefault), WTFMove(stringWithDefault), WTFMove(stringWithoutDefault), WTFMove(booleanWithDefault), WTFMove(booleanWithoutDefault), WTFMove(sequenceOfStrings), WTFMove(restrictedDouble), WTFMove(unrestrictedDouble), WTFMove(restrictedDoubleWithDefault), WTFMove(unrestrictedDoubleWithDefault), WTFMove(restrictedFloat), WTFMove(unrestrictedFloat), WTFMove(restrictedFloatWithDefault), WTFMove(unrestrictedFloatWithDefault), WTFMove(smallIntegerClamped), WTFMove(smallIntegerWithDefault), WTFMove(smallUnsignedIntegerEnforcedRange), WTFMove(smallUnsignedIntegerWithDefault), WTFMove(integer), WTFMove(integerWithDefault), WTFMove(unsignedInteger), WTFMove(unsignedIntegerWithDefault), WTFMove(largeInteger), WTFMove(largeIntegerWithDefault), WTFMove(unsignedLargeInteger), WTFMove(unsignedLargeIntegerWithDefault), WTFMove(nullableNode), WTFMove(anyValue), WTFMove(anyTypedefValue), dictionaryMember.value() };
return TestObj::Dictionary { WTFMove(enumerationValueWithoutDefault), WTFMove(enumerationValueWithDefault), WTFMove(enumerationValueWithEmptyStringDefault), WTFMove(stringWithDefault), WTFMove(stringWithoutDefault), WTFMove(booleanWithDefault), WTFMove(booleanWithoutDefault), WTFMove(sequenceOfStrings), WTFMove(restrictedDouble), WTFMove(unrestrictedDouble), WTFMove(restrictedDoubleWithDefault), WTFMove(unrestrictedDoubleWithDefault), WTFMove(restrictedFloat), WTFMove(unrestrictedFloat), WTFMove(restrictedFloatWithDefault), WTFMove(unrestrictedFloatWithDefault), WTFMove(smallIntegerClamped), WTFMove(smallIntegerWithDefault), WTFMove(smallUnsignedIntegerEnforcedRange), WTFMove(smallUnsignedIntegerWithDefault), WTFMove(integer), WTFMove(integerWithDefault), WTFMove(unsignedInteger), WTFMove(unsignedIntegerWithDefault), WTFMove(largeInteger), WTFMove(largeIntegerWithDefault), WTFMove(unsignedLargeInteger), WTFMove(unsignedLargeIntegerWithDefault), WTFMove(nullableNode), WTFMove(anyValue), WTFMove(anyValueWithNullDefault), WTFMove(anyTypedefValue), dictionaryMember.value() };
}

template<> Optional<TestObj::DictionaryThatShouldNotTolerateNull> convertDictionary<TestObj::DictionaryThatShouldNotTolerateNull>(ExecState& state, JSValue value)
@@ -459,6 +459,7 @@ dictionary TestDictionary {
unsigned long long unsignedLargeIntegerWithDefault = 0;
Node? nullableNode = null;
any anyValue;
any anyValueWithNullDefault = null;
AnyTypedef anyTypedefValue;
TestDictionaryThatShouldTolerateNull dictionaryMember;
};
@@ -31,13 +31,14 @@

namespace WebCore {

CustomEvent::CustomEvent()
CustomEvent::CustomEvent(IsTrusted isTrusted)
: Event(isTrusted)
{
}

CustomEvent::CustomEvent(const AtomicString& type, const CustomEventInit& initializer)
: Event(type, initializer)
, m_detail(initializer.detail)
CustomEvent::CustomEvent(JSC::ExecState& state, const AtomicString& type, const Init& initializer, IsTrusted isTrusted)
: Event(type, initializer, isTrusted)
, m_detail(state.vm(), initializer.detail)
{
}

@@ -32,22 +32,27 @@

namespace WebCore {

struct CustomEventInit : public EventInit {
Deprecated::ScriptValue detail;
};

class CustomEvent final : public Event {
public:
virtual ~CustomEvent();

static Ref<CustomEvent> createForBindings()
static Ref<CustomEvent> create(IsTrusted isTrusted = IsTrusted::No)
{
return adoptRef(*new CustomEvent);
return adoptRef(*new CustomEvent(isTrusted));
}

static Ref<CustomEvent> createForBindings(const AtomicString& type, const CustomEventInit& initializer)
struct Init : public EventInit {
Init(bool bubbles, bool cancelable, bool composed, JSC::JSValue detail)
: EventInit(bubbles, cancelable, composed)
, detail(detail)
{ }

JSC::JSValue detail;
};

static Ref<CustomEvent> create(JSC::ExecState& state, const AtomicString& type, const Init& initializer, IsTrusted isTrusted = IsTrusted::No)
{
return adoptRef(*new CustomEvent(type, initializer));
return adoptRef(*new CustomEvent(state, type, initializer, isTrusted));
}

void initCustomEvent(JSC::ExecState&, const AtomicString& type, bool canBubble, bool cancelable, JSC::JSValue detail = JSC::JSValue::JSUndefined);
@@ -59,8 +64,8 @@ class CustomEvent final : public Event {
RefPtr<SerializedScriptValue> trySerializeDetail(JSC::ExecState&);

private:
CustomEvent();
CustomEvent(const AtomicString& type, const CustomEventInit& initializer);
CustomEvent(IsTrusted);
CustomEvent(JSC::ExecState&, const AtomicString& type, const Init& initializer, IsTrusted);

Deprecated::ScriptValue m_detail; // FIXME: Why is it OK to use a strong reference here? What prevents a reference cycle?
RefPtr<SerializedScriptValue> m_serializedDetail;
@@ -24,10 +24,16 @@
*/

// Introduced in DOM Level 3:
// FIXME: This should be exposed to workers as well.
[
ConstructorTemplate=Event,
Constructor(DOMString type, optional CustomEventInit eventInitDict),
ConstructorCallWith=ScriptState,
] interface CustomEvent : Event {
[InitializedByEventConstructor, CustomGetter] readonly attribute any detail;
[CustomGetter] readonly attribute any detail;

[CallWith=ScriptState] void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any detail);
};

dictionary CustomEventInit : EventInit {
any detail = null;
};
@@ -4129,7 +4129,7 @@ RefPtr<Event> Document::createEvent(const String& type, ExceptionCode& ec)
// <https://dom.spec.whatwg.org/#dom-document-createevent>.

if (equalLettersIgnoringASCIICase(type, "customevent"))
return CustomEvent::createForBindings();
return CustomEvent::create();
if (equalLettersIgnoringASCIICase(type, "event") || equalLettersIgnoringASCIICase(type, "events") || equalLettersIgnoringASCIICase(type, "htmlevents"))
return Event::createForBindings();
if (equalLettersIgnoringASCIICase(type, "keyboardevent") || equalLettersIgnoringASCIICase(type, "keyboardevents"))
@@ -31,8 +31,9 @@

namespace WebCore {

Event::Event()
: m_createTime(convertSecondsToDOMTimeStamp(currentTime()))
Event::Event(IsTrusted isTrusted)
: m_isTrusted(isTrusted == IsTrusted::Yes)
, m_createTime(convertSecondsToDOMTimeStamp(currentTime()))
{
}

@@ -190,7 +190,7 @@ class Event : public ScriptWrappable, public RefCounted<Event> {
virtual EventTarget* relatedTarget() const { return nullptr; }

protected:
Event();
Event(IsTrusted = IsTrusted::No);
WEBCORE_EXPORT Event(const AtomicString& type, bool canBubble, bool cancelable);
Event(const AtomicString& type, bool canBubble, bool cancelable, double timestamp);
Event(const AtomicString& type, const EventInit&, IsTrusted = IsTrusted::No);

0 comments on commit 12d2ab1

Please sign in to comment.