Changeset 289058 in webkit


Ignore:
Timestamp:
Feb 3, 2022 9:58:13 AM (6 months ago)
Author:
Chris Dumez
Message:

Implement AbortSignal.timeout()
https://bugs.webkit.org/show_bug.cgi?id=236039

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Import AbortSignal.timeout() tests from upstream WPT.

  • web-platform-tests/dom/abort/AbortSignal.any-expected.txt:
  • web-platform-tests/dom/abort/AbortSignal.any.js:

(async_test.t.signal.onabort.t.step_func_done):
(async_test.t.string_appeared_here.signal.onabort.t.step_func):

  • web-platform-tests/dom/abort/AbortSignal.any.worker-expected.txt:
  • web-platform-tests/dom/abort/abort-signal-timeout-expected.txt: Added.
  • web-platform-tests/dom/abort/abort-signal-timeout.html: Added.
  • web-platform-tests/dom/abort/w3c-import.log:

Source/WebCore:

Implement the new AbortSignal.timeout() as per:

Test: imported/w3c/web-platform-tests/dom/abort/abort-signal-timeout.html

  • bindings/js/JSAbortSignalCustom.cpp:

(WebCore::JSAbortSignalOwner::isReachableFromOpaqueRoots):

  • dom/AbortSignal.cpp:

(WebCore::AbortSignal::timeout):
(WebCore::AbortSignal::eventListenersDidChange):

  • dom/AbortSignal.h:
  • dom/AbortSignal.idl:
  • page/DOMTimer.cpp:

(WebCore::DOMTimer::DOMTimer):
(WebCore::DOMTimer::install):
(WebCore::DOMTimer::fired):

  • page/DOMTimer.h:
Location:
trunk
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r289048 r289058  
     12022-02-03  Chris Dumez  <cdumez@apple.com>
     2
     3        Implement AbortSignal.timeout()
     4        https://bugs.webkit.org/show_bug.cgi?id=236039
     5
     6        Reviewed by Darin Adler.
     7
     8        Import AbortSignal.timeout() tests from upstream WPT.
     9
     10        * web-platform-tests/dom/abort/AbortSignal.any-expected.txt:
     11        * web-platform-tests/dom/abort/AbortSignal.any.js:
     12        (async_test.t.signal.onabort.t.step_func_done):
     13        (async_test.t.string_appeared_here.signal.onabort.t.step_func):
     14        * web-platform-tests/dom/abort/AbortSignal.any.worker-expected.txt:
     15        * web-platform-tests/dom/abort/abort-signal-timeout-expected.txt: Added.
     16        * web-platform-tests/dom/abort/abort-signal-timeout.html: Added.
     17        * web-platform-tests/dom/abort/w3c-import.log:
     18
    1192022-02-03  Antoine Quint  <graouts@webkit.org>
    220
  • trunk/LayoutTests/imported/w3c/web-platform-tests/dom/abort/AbortSignal.any-expected.txt

    r279015 r289058  
    22PASS the AbortSignal.abort() static returns an already aborted signal
    33PASS signal returned by AbortSignal.abort() should not fire abort event
     4PASS AbortSignal.timeout() returns a non-aborted signal
     5PASS Signal returned by AbortSignal.timeout() times out
     6PASS AbortSignal timeouts fire in order
    47
  • trunk/LayoutTests/imported/w3c/web-platform-tests/dom/abort/AbortSignal.any.js

    r279015 r289058  
    1111  t.step_timeout(() => { t.done(); }, 2000);
    1212}, "signal returned by AbortSignal.abort() should not fire abort event");
     13
     14test(t => {
     15  const signal = AbortSignal.timeout(0);
     16  assert_true(signal instanceof AbortSignal, "returned object is an AbortSignal");
     17  assert_false(signal.aborted, "returned signal is not already aborted");
     18}, "AbortSignal.timeout() returns a non-aborted signal");
     19
     20async_test(t => {
     21  const signal = AbortSignal.timeout(5);
     22  signal.onabort = t.step_func_done(() => {
     23    assert_true(signal.aborted, "signal is aborted");
     24    assert_true(signal.reason instanceof DOMException, "signal.reason is a DOMException");
     25    assert_equals(signal.reason.name, "TimeoutError", "signal.reason is a TimeoutError");
     26  });
     27}, "Signal returned by AbortSignal.timeout() times out");
     28
     29async_test(t => {
     30  let result = "";
     31  for (const value of ["1", "2", "3"]) {
     32    const signal = AbortSignal.timeout(5);
     33    signal.onabort = t.step_func(() => { result += value; });
     34  }
     35
     36  const signal = AbortSignal.timeout(5);
     37  signal.onabort = t.step_func_done(() => {
     38    assert_equals(result, "123", "Timeout order should be 123");
     39  });
     40}, "AbortSignal timeouts fire in order");
  • trunk/LayoutTests/imported/w3c/web-platform-tests/dom/abort/AbortSignal.any.worker-expected.txt

    r279015 r289058  
    22PASS the AbortSignal.abort() static returns an already aborted signal
    33PASS signal returned by AbortSignal.abort() should not fire abort event
     4PASS AbortSignal.timeout() returns a non-aborted signal
     5PASS Signal returned by AbortSignal.timeout() times out
     6PASS AbortSignal timeouts fire in order
    47
  • trunk/LayoutTests/imported/w3c/web-platform-tests/dom/abort/w3c-import.log

    r287788 r289058  
    1616List of files:
    1717/LayoutTests/imported/w3c/web-platform-tests/dom/abort/AbortSignal.any.js
     18/LayoutTests/imported/w3c/web-platform-tests/dom/abort/abort-signal-timeout.html
    1819/LayoutTests/imported/w3c/web-platform-tests/dom/abort/event.any.js
    1920/LayoutTests/imported/w3c/web-platform-tests/dom/abort/reason-constructor.html
  • trunk/Source/WebCore/ChangeLog

    r289057 r289058  
     12022-02-03  Chris Dumez  <cdumez@apple.com>
     2
     3        Implement AbortSignal.timeout()
     4        https://bugs.webkit.org/show_bug.cgi?id=236039
     5
     6        Reviewed by Darin Adler.
     7
     8        Implement the new AbortSignal.timeout() as per:
     9        - https://dom.spec.whatwg.org/#dom-abortsignal-timeout
     10
     11        Test: imported/w3c/web-platform-tests/dom/abort/abort-signal-timeout.html
     12
     13        * bindings/js/JSAbortSignalCustom.cpp:
     14        (WebCore::JSAbortSignalOwner::isReachableFromOpaqueRoots):
     15        * dom/AbortSignal.cpp:
     16        (WebCore::AbortSignal::timeout):
     17        (WebCore::AbortSignal::eventListenersDidChange):
     18        * dom/AbortSignal.h:
     19        * dom/AbortSignal.idl:
     20        * page/DOMTimer.cpp:
     21        (WebCore::DOMTimer::DOMTimer):
     22        (WebCore::DOMTimer::install):
     23        (WebCore::DOMTimer::fired):
     24        * page/DOMTimer.h:
     25
    1262022-02-03  Mark Lam  <mark.lam@apple.com>
    227
  • trunk/Source/WebCore/bindings/js/JSAbortSignalCustom.cpp

    r285428 r289058  
    11/*
    2 * Copyright (C) 2019-2021 Apple Inc. All rights reserved.
     2* Copyright (C) 2019-2022 Apple Inc. All rights reserved.
    33*
    44* Redistribution and use in source and binary forms, with or without
     
    4444        return true;
    4545
     46    if (abortSignal.hasAbortEventListener() && abortSignal.hasActiveTimeoutTimer())
     47        return true;
     48
    4649    return visitor.containsOpaqueRoot(&abortSignal);
    4750}
  • trunk/Source/WebCore/dom/AbortSignal.cpp

    r287532 r289058  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#include "AbortAlgorithm.h"
    3030#include "DOMException.h"
     31#include "DOMTimer.h"
    3132#include "Event.h"
    3233#include "EventNames.h"
     
    5455}
    5556
     57// https://dom.spec.whatwg.org/#dom-abortsignal-timeout
     58Ref<AbortSignal> AbortSignal::timeout(ScriptExecutionContext& context, uint64_t milliseconds)
     59{
     60    auto signal = adoptRef(*new AbortSignal(&context));
     61    signal->setHasActiveTimeoutTimer(true);
     62    auto action = [signal](ScriptExecutionContext& context) mutable {
     63        signal->setHasActiveTimeoutTimer(false);
     64
     65        auto* globalObject = jsCast<JSDOMGlobalObject*>(context.globalObject());
     66        if (!globalObject)
     67            return;
     68
     69        auto& vm = globalObject->vm();
     70        Locker locker { vm.apiLock() };
     71        signal->signalAbort(toJS(globalObject, globalObject, DOMException::create(TimeoutError)));
     72    };
     73    DOMTimer::install(context, WTFMove(action), Seconds::fromMilliseconds(milliseconds), true);
     74    return signal;
     75}
     76
    5677AbortSignal::AbortSignal(ScriptExecutionContext* context, Aborted aborted, JSC::JSValue reason)
    5778    : ContextDestructionObserver(context)
     
    6182    ASSERT(reason);
    6283}
     84
     85AbortSignal::~AbortSignal() = default;
    6386
    6487// https://dom.spec.whatwg.org/#abortsignal-signal-abort
     
    103126}
    104127
     128void AbortSignal::eventListenersDidChange()
     129{
     130    m_hasAbortEventListener = hasEventListeners(eventNames().abortEvent);
     131}
     132
    105133bool AbortSignal::whenSignalAborted(AbortSignal& signal, Ref<AbortAlgorithm>&& algorithm)
    106134{
  • trunk/Source/WebCore/dom/AbortSignal.h

    r287532 r289058  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4444public:
    4545    static Ref<AbortSignal> create(ScriptExecutionContext*);
     46    WEBCORE_EXPORT ~AbortSignal();
    4647
    4748    static Ref<AbortSignal> abort(JSDOMGlobalObject&, ScriptExecutionContext&, JSC::JSValue reason);
     49    static Ref<AbortSignal> timeout(ScriptExecutionContext&, uint64_t milliseconds);
    4850
    4951    static bool whenSignalAborted(AbortSignal&, Ref<AbortAlgorithm>&&);
     
    5456    bool aborted() const { return m_aborted; }
    5557    const JSValueInWrappedObject& reason() const { return m_reason; }
     58
     59    bool hasActiveTimeoutTimer() const { return m_hasActiveTimeoutTimer; }
     60    bool hasAbortEventListener() const { return m_hasAbortEventListener; }
    5661
    5762    using RefCounted::ref;
     
    6974    explicit AbortSignal(ScriptExecutionContext*, Aborted = Aborted::No, JSC::JSValue reason = JSC::jsUndefined());
    7075
     76    void setHasActiveTimeoutTimer(bool hasActiveTimeoutTimer) { m_hasActiveTimeoutTimer = hasActiveTimeoutTimer; }
     77
    7178    // EventTarget.
    7279    EventTargetInterface eventTargetInterface() const final { return AbortSignalEventTargetInterfaceType; }
     
    7481    void refEventTarget() final { ref(); }
    7582    void derefEventTarget() final { deref(); }
     83    void eventListenersDidChange() final;
    7684   
    7785    bool m_aborted { false };
     
    7987    WeakPtr<AbortSignal> m_followingSignal;
    8088    JSValueInWrappedObject m_reason;
     89    bool m_hasActiveTimeoutTimer { false };
     90    bool m_hasAbortEventListener { false };
    8191};
    8292
  • trunk/Source/WebCore/dom/AbortSignal.idl

    r286904 r289058  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3434
    3535    [NewObject, CallWith=ScriptExecutionContext&GlobalObject] static AbortSignal abort(optional any reason);
     36    [NewObject, CallWith=ScriptExecutionContext] static AbortSignal timeout([EnforceRange] unsigned long long milliseconds);
     37
    3638    readonly attribute boolean aborted;
    3739    readonly attribute any reason;
  • trunk/Source/WebCore/page/DOMTimer.cpp

    r288069 r289058  
    156156bool NestedTimersMap::isTrackingNestedTimers = false;
    157157
    158 DOMTimer::DOMTimer(ScriptExecutionContext& context, std::unique_ptr<ScheduledAction> action, Seconds interval, bool singleShot)
     158DOMTimer::DOMTimer(ScriptExecutionContext& context, Function<void(ScriptExecutionContext&)>&& action, Seconds interval, bool singleShot)
    159159    : SuspendableTimerBase(&context)
    160160    , m_nestingLevel(context.timerNestingLevel())
     
    174174
    175175int DOMTimer::install(ScriptExecutionContext& context, std::unique_ptr<ScheduledAction> action, Seconds timeout, bool singleShot)
     176{
     177    auto actionFunction = [action = WTFMove(action)](ScriptExecutionContext& context) mutable {
     178        action->execute(context);
     179    };
     180    return DOMTimer::install(context, WTFMove(actionFunction), timeout, singleShot);
     181}
     182
     183int DOMTimer::install(ScriptExecutionContext& context, Function<void(ScriptExecutionContext&)>&& action, Seconds timeout, bool singleShot)
    176184{
    177185    Ref<DOMTimer> timer = adoptRef(*new DOMTimer(context, WTFMove(action), timeout, singleShot));
     
    317325        }
    318326
    319         m_action->execute(context);
     327        m_action(context);
    320328
    321329        InspectorInstrumentation::didFireTimer(context, m_timeoutId, oneShot);
     
    335343    ContentChangeObserver::DOMTimerScope observingScope(dynamicDowncast<Document>(context), *this);
    336344#endif
    337     m_action->execute(context);
     345    m_action(context);
    338346
    339347    InspectorInstrumentation::didFireTimer(context, m_timeoutId, oneShot);
  • trunk/Source/WebCore/page/DOMTimer.h

    r278253 r289058  
    5656    // and returns its Id.
    5757    static int install(ScriptExecutionContext&, std::unique_ptr<ScheduledAction>, Seconds timeout, bool singleShot);
     58    static int install(ScriptExecutionContext&, Function<void(ScriptExecutionContext&)>&&, Seconds timeout, bool singleShot);
    5859    static void removeById(ScriptExecutionContext&, int timeoutId);
    5960
     
    6566
    6667private:
    67     DOMTimer(ScriptExecutionContext&, std::unique_ptr<ScheduledAction>, Seconds interval, bool singleShot);
     68    DOMTimer(ScriptExecutionContext&, Function<void(ScriptExecutionContext&)>&&, Seconds interval, bool singleShot);
    6869    friend class Internals;
    6970
     
    8990    int m_timeoutId;
    9091    int m_nestingLevel;
    91     std::unique_ptr<ScheduledAction> m_action;
     92    Function<void(ScriptExecutionContext&)> m_action;
    9293    Seconds m_originalInterval;
    9394    TimerThrottleState m_throttleState;
Note: See TracChangeset for help on using the changeset viewer.