Changeset 213108 in webkit


Ignore:
Timestamp:
Feb 27, 2017 5:34:35 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

[WebRTC] Support modern RTCStatsReport
https://bugs.webkit.org/show_bug.cgi?id=166916
<rdar://problem/30293780>

Patch by Youenn Fablet <youenn@apple.com> on 2017-02-27
Reviewed by Alex Christensen.

Updating binding generator and IDL parser to handle maplike.
Covered by binding tests.

Added support for maplike binding from JS wrapper to DOM class.
The principle is to have the JSXX wrapper having a @backingMap slot containing a Map.
All maplike methods are forwarded to the corresponding Map methods.
The XX object is responsible to add key/value pairs using a helper routine.
The creation of the Map is done at creation of the JSXX wrapper.

DOM class is interacting with the map through DOMMapLike.
Extracted DOMGuarded from DOM promise implementation.
This allows reusing this code for DOMMapLike.

Covered by binding tests and manual tests.

  • CMakeLists.txt:
  • DerivedSources.make:
  • Modules/mediastream/RTCStatsReport.h:

(WebCore::RTCStatsReport::InboundRTPStreamStats::InboundRTPStreamStats):
(WebCore::RTCStatsReport::OutboundRTPStreamStats::OutboundRTPStreamStats):
(WebCore::RTCStatsReport::create):
(WebCore::RTCStatsReport::synchronizeBackingMap):
(WebCore::RTCStatsReport::backingMap):
(WebCore::RTCStatsReport::addStats):

  • Modules/mediastream/RTCStatsReport.idl:
  • Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:

(WebCore::fromStdString):
(WebCore::fillRTCStats):
(WebCore::fillRTCRTPStreamStats):
(WebCore::fillInboundRTPStreamStats):
(WebCore::fillOutboundRTPStreamStats):
(WebCore::LibWebRTCMediaEndpoint::StatsCollector::OnStatsDelivered):

  • Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/JSDOMBindingInternals.js: Added.

(mapLikeForEach):

  • bindings/js/JSDOMGlobalObject.cpp:

(WebCore::JSDOMGlobalObject::visitChildren):

  • bindings/js/JSDOMGlobalObject.h:
  • bindings/js/JSDOMGuardedObject.cpp: Added.

(WebCore::DOMGuardedObject::DOMGuardedObject):
(WebCore::DOMGuardedObject::~DOMGuardedObject):
(WebCore::DOMGuardedObject::clear):
(WebCore::DOMGuardedObject::contextDestroyed):

  • bindings/js/JSDOMGuardedObject.h: Added.

(WebCore::DOMGuardedObject::isSuspended):
(WebCore::DOMGuardedObject::visitAggregate):
(WebCore::DOMGuardedObject::guardedObject):
(WebCore::DOMGuardedObject::globalObject):
(WebCore::DOMGuardedObject::isEmpty):
(WebCore::DOMGuarded::DOMGuarded):
(WebCore::DOMGuarded::guarded):

  • bindings/js/JSDOMMapLike.cpp: Added.

(WebCore::getBackingMap):
(WebCore::initializeBackingMap):
(WebCore::createBackingMap):
(WebCore::forwardAttributeGetterToBackingMap):
(WebCore::forwardFunctionCallToBackingMap):
(WebCore::forwardForEachCallToBackingMap):

  • bindings/js/JSDOMMapLike.h: Added.

(WebCore::DOMMapLike::set):
(WebCore::synchronizeBackingMap):
(WebCore::forwardSizeToMapLike):
(WebCore::forwardEntriesToMapLike):
(WebCore::forwardKeysToMapLike):
(WebCore::forwardValuesToMapLike):
(WebCore::forwardClearToMapLike):
(WebCore::forwardForEachToMapLike):
(WebCore::forwardHasToMapLike):
(WebCore::forwardAddToMapLike):
(WebCore::forwardDeleteToMapLike):

  • bindings/js/JSDOMPromise.cpp:

(WebCore::DeferredPromise::promise):
(WebCore::DeferredPromise::reject):

  • bindings/js/JSDOMPromise.h:

(WebCore::DeferredPromise::resolve):
(WebCore::DeferredPromise::resolveWithNewlyCreated):
(WebCore::DeferredPromise::reject):
(WebCore::DeferredPromise::resolveWithCallback):
(WebCore::DeferredPromise::rejectWithCallback):
(WebCore::DeferredPromise::DeferredPromise):
(WebCore::DeferredPromise::deferred):

  • bindings/js/WebCoreBuiltinNames.h:
  • bindings/scripts/CodeGeneratorJS.pm:

(PrototypeFunctionCount):
(GeneratePropertiesHashTable):
(InterfaceNeedsIterator):
(GenerateImplementation):
(GenerateParametersCheck):

  • bindings/scripts/IDLParser.pm:

(assert):
(parseAttributeOrOperationOrIterator):
(parseSerializer):
(parseAttributeOrOperationRest):
(parseAttribute):
(parseAttributeRest):
(parseOperationOrIterator):
(parseOptionalIterableInterface):
(parseMapLikeRest):
(parseMapLikeProperties):
(parseOperationRest):
(applyMemberList):

  • bindings/scripts/test/JS/JSMapLike.cpp: Added.
  • bindings/scripts/test/JS/JSMapLike.h: Added.
  • bindings/scripts/test/JS/JSReadOnlyMapLike.cpp: Added.
  • bindings/scripts/test/JS/JSReadOnlyMapLike.h: Added.
  • bindings/scripts/test/TestMapLike.idl: Added.
  • bindings/scripts/test/TestReadOnlyMapLike.idl: Added.
Location:
trunk/Source
Files:
11 added
1 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/ThirdParty/libwebrtc/Source/webrtc/api/stats/rtcstats_objects.h

    r210942 r213108  
    1515
    1616#include "webrtc/api/stats/rtcstats.h"
     17#include "webrtc/base/export.h"
    1718
    1819namespace webrtc {
     
    302303// TODO(hbos): Finish implementation and support the remote case
    303304// |is_remote = true|. Tracking bug crbug.com/657855
    304 class RTCInboundRTPStreamStats final : public RTCRTPStreamStats {
     305class WEBRTC_EXPORT RTCInboundRTPStreamStats final : public RTCRTPStreamStats {
    305306 public:
    306307  WEBRTC_RTCSTATS_DECL();
     
    344345// TODO(hbos): Finish implementation and support the remote case
    345346// |is_remote = true|. Tracking bug crbug.com/657856
    346 class RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
     347class WEBRTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
    347348 public:
    348349  WEBRTC_RTCSTATS_DECL();
  • trunk/Source/ThirdParty/libwebrtc/Source/webrtc/api/stats/rtcstatsreport.h

    r210942 r213108  
    1818
    1919#include "webrtc/api/stats/rtcstats.h"
     20#include "webrtc/base/export.h"
    2021#include "webrtc/base/refcount.h"
    2122#include "webrtc/base/scoped_ref_ptr.h"
     
    2526// A collection of stats.
    2627// This is accessible as a map from |RTCStats::id| to |RTCStats|.
    27 class RTCStatsReport : public rtc::RefCountInterface {
     28class WEBRTC_EXPORT RTCStatsReport : public rtc::RefCountInterface {
    2829 public:
    2930  typedef std::map<std::string, std::unique_ptr<const RTCStats>> StatsMap;
  • trunk/Source/WebCore/CMakeLists.txt

    r213081 r213108  
    936936    Modules/mediastream/RTCRtpTransceiver.cpp
    937937    Modules/mediastream/RTCSessionDescription.cpp
    938     Modules/mediastream/RTCStatsReport.cpp
    939938    Modules/mediastream/RTCTrackEvent.cpp
    940939    Modules/mediastream/SDPProcessor.cpp
     
    11221121    bindings/js/JSDOMGlobalObject.cpp
    11231122    bindings/js/JSDOMGlobalObjectTask.cpp
     1123    bindings/js/JSDOMGuardedObject.cpp
     1124    bindings/js/JSDOMMapLike.cpp
    11241125    bindings/js/JSDOMPromise.cpp
    11251126    bindings/js/JSDOMStringMapCustom.cpp
     
    37013702    ${WEBCORE_DIR}/Modules/streams/WritableStream.js
    37023703    ${WEBCORE_DIR}/Modules/streams/WritableStreamInternals.js
     3704    ${WEBCORE_DIR}/bindings/js/JSDOMBindingInternals.js
    37033705    ${WEBCORE_DIR}/xml/XMLHttpRequest.js
    37043706)
  • trunk/Source/WebCore/ChangeLog

    r213107 r213108  
     12017-02-27  Youenn Fablet  <youenn@apple.com>
     2
     3        [WebRTC] Support modern RTCStatsReport
     4        https://bugs.webkit.org/show_bug.cgi?id=166916
     5        <rdar://problem/30293780>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Updating binding generator and IDL parser to handle maplike.
     10        Covered by binding tests.
     11
     12        Added support for maplike binding from JS wrapper to DOM class.
     13        The principle is to have the JSXX wrapper having a @backingMap slot containing a Map.
     14        All maplike methods are forwarded to the corresponding Map methods.
     15        The XX object is responsible to add key/value pairs using a helper routine.
     16        The creation of the Map is done at creation of the JSXX wrapper.
     17
     18        DOM class is interacting with the map through DOMMapLike.
     19        Extracted DOMGuarded from DOM promise implementation.
     20        This allows reusing this code for DOMMapLike.
     21
     22        Covered by binding tests and manual tests.
     23
     24        * CMakeLists.txt:
     25        * DerivedSources.make:
     26        * Modules/mediastream/RTCStatsReport.h:
     27        (WebCore::RTCStatsReport::InboundRTPStreamStats::InboundRTPStreamStats):
     28        (WebCore::RTCStatsReport::OutboundRTPStreamStats::OutboundRTPStreamStats):
     29        (WebCore::RTCStatsReport::create):
     30        (WebCore::RTCStatsReport::synchronizeBackingMap):
     31        (WebCore::RTCStatsReport::backingMap):
     32        (WebCore::RTCStatsReport::addStats):
     33        * Modules/mediastream/RTCStatsReport.idl:
     34        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
     35        (WebCore::fromStdString):
     36        (WebCore::fillRTCStats):
     37        (WebCore::fillRTCRTPStreamStats):
     38        (WebCore::fillInboundRTPStreamStats):
     39        (WebCore::fillOutboundRTPStreamStats):
     40        (WebCore::LibWebRTCMediaEndpoint::StatsCollector::OnStatsDelivered):
     41        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
     42        * WebCore.xcodeproj/project.pbxproj:
     43        * bindings/js/JSDOMBindingInternals.js: Added.
     44        (mapLikeForEach):
     45        * bindings/js/JSDOMGlobalObject.cpp:
     46        (WebCore::JSDOMGlobalObject::visitChildren):
     47        * bindings/js/JSDOMGlobalObject.h:
     48        * bindings/js/JSDOMGuardedObject.cpp: Added.
     49        (WebCore::DOMGuardedObject::DOMGuardedObject):
     50        (WebCore::DOMGuardedObject::~DOMGuardedObject):
     51        (WebCore::DOMGuardedObject::clear):
     52        (WebCore::DOMGuardedObject::contextDestroyed):
     53        * bindings/js/JSDOMGuardedObject.h: Added.
     54        (WebCore::DOMGuardedObject::isSuspended):
     55        (WebCore::DOMGuardedObject::visitAggregate):
     56        (WebCore::DOMGuardedObject::guardedObject):
     57        (WebCore::DOMGuardedObject::globalObject):
     58        (WebCore::DOMGuardedObject::isEmpty):
     59        (WebCore::DOMGuarded::DOMGuarded):
     60        (WebCore::DOMGuarded::guarded):
     61        * bindings/js/JSDOMMapLike.cpp: Added.
     62        (WebCore::getBackingMap):
     63        (WebCore::initializeBackingMap):
     64        (WebCore::createBackingMap):
     65        (WebCore::forwardAttributeGetterToBackingMap):
     66        (WebCore::forwardFunctionCallToBackingMap):
     67        (WebCore::forwardForEachCallToBackingMap):
     68        * bindings/js/JSDOMMapLike.h: Added.
     69        (WebCore::DOMMapLike::set):
     70        (WebCore::synchronizeBackingMap):
     71        (WebCore::forwardSizeToMapLike):
     72        (WebCore::forwardEntriesToMapLike):
     73        (WebCore::forwardKeysToMapLike):
     74        (WebCore::forwardValuesToMapLike):
     75        (WebCore::forwardClearToMapLike):
     76        (WebCore::forwardForEachToMapLike):
     77        (WebCore::forwardHasToMapLike):
     78        (WebCore::forwardAddToMapLike):
     79        (WebCore::forwardDeleteToMapLike):
     80        * bindings/js/JSDOMPromise.cpp:
     81        (WebCore::DeferredPromise::promise):
     82        (WebCore::DeferredPromise::reject):
     83        * bindings/js/JSDOMPromise.h:
     84        (WebCore::DeferredPromise::resolve):
     85        (WebCore::DeferredPromise::resolveWithNewlyCreated):
     86        (WebCore::DeferredPromise::reject):
     87        (WebCore::DeferredPromise::resolveWithCallback):
     88        (WebCore::DeferredPromise::rejectWithCallback):
     89        (WebCore::DeferredPromise::DeferredPromise):
     90        (WebCore::DeferredPromise::deferred):
     91        * bindings/js/WebCoreBuiltinNames.h:
     92        * bindings/scripts/CodeGeneratorJS.pm:
     93        (PrototypeFunctionCount):
     94        (GeneratePropertiesHashTable):
     95        (InterfaceNeedsIterator):
     96        (GenerateImplementation):
     97        (GenerateParametersCheck):
     98        * bindings/scripts/IDLParser.pm:
     99        (assert):
     100        (parseAttributeOrOperationOrIterator):
     101        (parseSerializer):
     102        (parseAttributeOrOperationRest):
     103        (parseAttribute):
     104        (parseAttributeRest):
     105        (parseOperationOrIterator):
     106        (parseOptionalIterableInterface):
     107        (parseMapLikeRest):
     108        (parseMapLikeProperties):
     109        (parseOperationRest):
     110        (applyMemberList):
     111        * bindings/scripts/test/JS/JSMapLike.cpp: Added.
     112        * bindings/scripts/test/JS/JSMapLike.h: Added.
     113        * bindings/scripts/test/JS/JSReadOnlyMapLike.cpp: Added.
     114        * bindings/scripts/test/JS/JSReadOnlyMapLike.h: Added.
     115        * bindings/scripts/test/TestMapLike.idl: Added.
     116        * bindings/scripts/test/TestReadOnlyMapLike.idl: Added.
     117
    11182017-02-27  Mark Lam  <mark.lam@apple.com>
    2119
  • trunk/Source/WebCore/DerivedSources.make

    r213081 r213108  
    13641364    $(WebCore)/Modules/streams/WritableStream.js \
    13651365    $(WebCore)/Modules/streams/WritableStreamInternals.js \
     1366    $(WebCore)/bindings/js/JSDOMBindingInternals.js \
    13661367    $(WebCore)/xml/XMLHttpRequest.js \
    13671368#
  • trunk/Source/WebCore/Modules/mediastream/RTCStatsReport.h

    r212329 r213108  
    11/*
    22 * Copyright (C) 2012 Google Inc. All rights reserved.
     3 * Copyright (C) 2017 Apple Inc. All rights reserved.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    2526#pragma once
    2627
    27 #include <wtf/Ref.h>
    28 #include <wtf/RefCounted.h>
     28#include "JSDOMMapLike.h"
    2929
    3030namespace WebCore {
     
    3434    static Ref<RTCStatsReport> create() { return adoptRef(*new RTCStatsReport); }
    3535
     36    void synchronizeBackingMap(Ref<DOMMapLike>&& mapLike) { m_mapLike = WTFMove(mapLike); }
     37    DOMMapLike* backingMap() { return m_mapLike.get(); }
     38
     39    template<typename Value> void addStats(typename Value::ParameterType&& value) { m_mapLike->set<IDLDOMString, Value>(value.id, std::forward<typename Value::ParameterType>(value)); }
     40
     41
     42    enum class Type {
     43        Codec,
     44        InboundRtp,
     45        OutboundRtp,
     46        PeerConnection,
     47        DataChannel,
     48        Track,
     49        Transport,
     50        CandidatePair,
     51        LocalCandidate,
     52        RemoteCandidate,
     53        Certificate
     54    };
     55    struct Stats {
     56        unsigned long long timestamp;
     57        Type type;
     58        String id;
     59    };
     60
     61    struct RTCRTPStreamStats : Stats {
     62        String ssrc;
     63        String associateStatsId;
     64        bool isRemote { false };
     65        String mediaType;
     66
     67        String mediaTrackId;
     68        String transportId;
     69        String codecId;
     70        unsigned long firCount { 0 };
     71        unsigned long pliCount { 0 };
     72        unsigned long nackCount { 0 };
     73        unsigned long sliCount { 0 };
     74        unsigned long long qpSum { 0 };
     75    };
     76
     77    struct InboundRTPStreamStats : RTCRTPStreamStats {
     78        InboundRTPStreamStats() { type = RTCStatsReport::Type::InboundRtp; }
     79
     80        String ssrc;
     81        String associateStatsId;
     82        bool isRemote { false };
     83        String mediaType;
     84        String mediaTrackId;
     85        String transportId;
     86        String codecId;
     87        unsigned long firCount { 0 };
     88        unsigned long pliCount { 0 };
     89        unsigned long nackCount { 0 };
     90        unsigned long sliCount { 0 };
     91        unsigned long long qpSum { 0 };
     92        unsigned long packetsReceived { 0 };
     93        unsigned long long bytesReceived { 0 };
     94        unsigned long packetsLost { 0 };
     95        double jitter { 0 };
     96        double fractionLost { 0 };
     97        unsigned long packetsDiscarded { 0 };
     98        unsigned long packetsRepaired { 0 };
     99        unsigned long burstPacketsLost { 0 };
     100        unsigned long burstPacketsDiscarded { 0 };
     101        unsigned long burstLossCount { 0 };
     102        unsigned long burstDiscardCount { 0 };
     103        double burstLossRate { 0 };
     104        double burstDiscardRate { 0 };
     105        double gapLossRate { 0 };
     106        double gapDiscardRate { 0 };
     107        unsigned long framesDecoded { 0 };
     108    };
     109
     110    struct OutboundRTPStreamStats : RTCRTPStreamStats {
     111        OutboundRTPStreamStats() { type = RTCStatsReport::Type::OutboundRtp; }
     112
     113        unsigned long packetsSent { 0 };
     114        unsigned long long bytesSent { 0 };
     115        double targetBitrate { 0 };
     116        double roundTripTime { 0 };
     117        unsigned long framesEncoded { 0 };
     118    };
     119
    36120private:
    37121    RTCStatsReport() = default;
     122
     123private:
     124    RefPtr<DOMMapLike> m_mapLike;
    38125};
    39126
  • trunk/Source/WebCore/Modules/mediastream/RTCStatsReport.idl

    r212329 r213108  
    2828    ImplementationLacksVTable,
    2929] interface RTCStatsReport {
    30     // FIXME: Make it setlike
    31     //readonly maplike<DOMString, object>;
     30    readonly maplike<DOMString, object>;
    3231};
     32
     33enum RTCStatsType {
     34    "codec",
     35    "inbound-rtp",
     36    "outbound-rtp",
     37    "peer-connection",
     38    "data-channel",
     39    "track",
     40    "transport",
     41    "candidate-pair",
     42    "local-candidate",
     43    "remote-candidate",
     44    "certificate"
     45};
     46
     47dictionary RTCStats {
     48    unsigned long long timestamp;
     49    RTCStatsType type;
     50    DOMString id;
     51
     52};
     53
     54dictionary RTCRTPStreamStats : RTCStats {
     55    DOMString ssrc;
     56    DOMString associateStatsId;
     57    boolean isRemote = false;
     58    DOMString mediaType;
     59    DOMString mediaTrackId;
     60    DOMString transportId;
     61    DOMString codecId;
     62    unsigned long firCount;
     63    unsigned long pliCount;
     64    unsigned long nackCount;
     65    unsigned long sliCount;
     66    unsigned long long qpSum;
     67};
     68
     69[ JSGenerateToJSObject ]
     70dictionary RTCInboundRTPStreamStats : RTCRTPStreamStats {
     71    unsigned long packetsReceived;
     72    unsigned long long bytesReceived;
     73    unsigned long packetsLost;
     74    double jitter;
     75    double fractionLost;
     76    unsigned long packetsDiscarded;
     77    unsigned long packetsRepaired;
     78    unsigned long burstPacketsLost;
     79    unsigned long burstPacketsDiscarded;
     80    unsigned long burstLossCount;
     81    unsigned long burstDiscardCount;
     82    double burstLossRate;
     83    double burstDiscardRate;
     84    double gapLossRate;
     85    double gapDiscardRate;
     86    unsigned long framesDecoded;
     87};
     88
     89[ JSGenerateToJSObject ]
     90dictionary RTCOutboundRTPStreamStats : RTCRTPStreamStats {
     91    unsigned long packetsSent;
     92    unsigned long long bytesSent;
     93    double targetBitrate;
     94    double roundTripTime;
     95    unsigned long framesEncoded;
     96};
  • trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp

    r212745 r213108  
    2929
    3030#include "EventNames.h"
     31#include "JSDOMConvert.h"
     32#include "JSRTCStatsReport.h"
    3133#include "LibWebRTCDataChannelHandler.h"
    3234#include "LibWebRTCPeerConnectionBackend.h"
     
    3941#include "RTCPeerConnection.h"
    4042#include "RTCSessionDescription.h"
     43#include "RTCStatsReport.h"
    4144#include "RTCTrackEvent.h"
    4245#include "RealtimeIncomingAudioSource.h"
     
    227230}
    228231
    229 void LibWebRTCMediaEndpoint::StatsCollector::OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report)
    230 {
    231     callOnMainThread([protectedThis = rtc::scoped_refptr<LibWebRTCMediaEndpoint::StatsCollector>(this), report] {
     232static inline String fromStdString(const std::string& value)
     233{
     234    return String(value.data(), value.length());
     235}
     236
     237static inline void fillRTCStats(RTCStatsReport::Stats& stats, const webrtc::RTCStats& rtcStats)
     238{
     239    stats.timestamp = rtcStats.timestamp_us();
     240    stats.id = fromStdString(rtcStats.id());
     241}
     242
     243static inline void fillRTCRTPStreamStats(RTCStatsReport::RTCRTPStreamStats& stats, const webrtc::RTCRTPStreamStats& rtcStats)
     244{
     245    fillRTCStats(stats, rtcStats);
     246    if (rtcStats.ssrc.is_defined())
     247        stats.ssrc = fromStdString(*rtcStats.ssrc);
     248    if (rtcStats.associate_stats_id.is_defined())
     249        stats.associateStatsId = fromStdString(*rtcStats.associate_stats_id);
     250    if (rtcStats.is_remote.is_defined())
     251        stats.isRemote = *rtcStats.is_remote;
     252    if (rtcStats.media_type.is_defined())
     253        stats.mediaType = fromStdString(*rtcStats.media_type);
     254    if (rtcStats.media_track_id.is_defined())
     255        stats.mediaTrackId = fromStdString(*rtcStats.media_track_id);
     256    if (rtcStats.transport_id.is_defined())
     257        stats.transportId = fromStdString(*rtcStats.transport_id);
     258    if (rtcStats.codec_id.is_defined())
     259        stats.codecId = fromStdString(*rtcStats.codec_id);
     260    if (rtcStats.fir_count.is_defined())
     261        stats.firCount = *rtcStats.fir_count;
     262    if (rtcStats.pli_count.is_defined())
     263        stats.pliCount = *rtcStats.pli_count;
     264    if (rtcStats.nack_count.is_defined())
     265        stats.nackCount = *rtcStats.nack_count;
     266    if (rtcStats.sli_count.is_defined())
     267        stats.sliCount = *rtcStats.sli_count;
     268    // FIXME: Set qpSum
     269    stats.qpSum = 0;
     270}
     271
     272static inline void fillInboundRTPStreamStats(RTCStatsReport::InboundRTPStreamStats& stats, const webrtc::RTCInboundRTPStreamStats& rtcStats)
     273{
     274    fillRTCRTPStreamStats(stats, rtcStats);
     275    if (rtcStats.packets_received.is_defined())
     276        stats.packetsReceived = *rtcStats.packets_received;
     277    if (rtcStats.bytes_received.is_defined())
     278        stats.bytesReceived = *rtcStats.bytes_received;
     279    if (rtcStats.packets_lost.is_defined())
     280        stats.packetsLost = *rtcStats.packets_lost;
     281    if (rtcStats.jitter.is_defined())
     282        stats.jitter = *rtcStats.jitter;
     283    if (rtcStats.fraction_lost.is_defined())
     284        stats.fractionLost = *rtcStats.fraction_lost;
     285    if (rtcStats.packets_discarded.is_defined())
     286        stats.packetsDiscarded = *rtcStats.packets_discarded;
     287    if (rtcStats.packets_repaired.is_defined())
     288        stats.packetsRepaired = *rtcStats.packets_repaired;
     289    if (rtcStats.burst_packets_lost.is_defined())
     290        stats.burstPacketsLost = *rtcStats.burst_packets_lost;
     291    if (rtcStats.burst_packets_discarded.is_defined())
     292        stats.burstPacketsDiscarded = *rtcStats.burst_packets_discarded;
     293    if (rtcStats.burst_loss_count.is_defined())
     294        stats.burstLossCount = *rtcStats.burst_loss_count;
     295    if (rtcStats.burst_discard_count.is_defined())
     296        stats.burstDiscardCount = *rtcStats.burst_discard_count;
     297    if (rtcStats.burst_loss_rate.is_defined())
     298        stats.burstLossRate = *rtcStats.burst_loss_rate;
     299    if (rtcStats.burst_discard_rate.is_defined())
     300        stats.burstDiscardRate = *rtcStats.burst_discard_rate;
     301    if (rtcStats.gap_loss_rate.is_defined())
     302        stats.gapLossRate = *rtcStats.gap_loss_rate;
     303    if (rtcStats.gap_discard_rate.is_defined())
     304        stats.gapDiscardRate = *rtcStats.gap_discard_rate;
     305    // FIXME: Set framesDecoded
     306    stats.framesDecoded = 0;
     307}
     308
     309static inline void fillOutboundRTPStreamStats(RTCStatsReport::OutboundRTPStreamStats& stats, const webrtc::RTCOutboundRTPStreamStats& rtcStats)
     310{
     311    fillRTCRTPStreamStats(stats, rtcStats);
     312
     313    if (rtcStats.packets_sent.is_defined())
     314        stats.packetsSent = *rtcStats.packets_sent;
     315    if (rtcStats.bytes_sent.is_defined())
     316        stats.bytesSent = *rtcStats.bytes_sent;
     317    if (rtcStats.target_bitrate.is_defined())
     318        stats.targetBitrate = *rtcStats.target_bitrate;
     319    if (rtcStats.round_trip_time.is_defined())
     320        stats.roundTripTime = *rtcStats.round_trip_time;
     321    // FIXME: Set framesEncoded
     322    stats.framesEncoded = 0;
     323}
     324
     325void LibWebRTCMediaEndpoint::StatsCollector::OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& rtcReport)
     326{
     327    callOnMainThread([protectedThis = rtc::scoped_refptr<LibWebRTCMediaEndpoint::StatsCollector>(this), rtcReport] {
    232328        if (protectedThis->m_endpoint->isStopped())
    233329            return;
    234330
    235         // FIXME: Fulfill promise with the report
    236         UNUSED_PARAM(report);
    237 
    238         protectedThis->m_endpoint->m_peerConnectionBackend.getStatsFailed(protectedThis->m_promise, Exception { TypeError, ASCIILiteral("Stats API is not yet implemented") });
     331        auto report = RTCStatsReport::create();
     332        protectedThis->m_endpoint->m_peerConnectionBackend.getStatsSucceeded(protectedThis->m_promise, report.copyRef());
     333        ASSERT(report->backingMap());
     334
     335        for (const auto& rtcStats : *rtcReport) {
     336            if (rtcStats.type() == webrtc::RTCInboundRTPStreamStats::kType) {
     337                RTCStatsReport::InboundRTPStreamStats stats;
     338                fillInboundRTPStreamStats(stats, static_cast<const webrtc::RTCInboundRTPStreamStats&>(rtcStats));
     339                report->addStats<IDLDictionary<RTCStatsReport::InboundRTPStreamStats>>(WTFMove(stats));
     340                return;
     341            }
     342            if (rtcStats.type() == webrtc::RTCOutboundRTPStreamStats::kType) {
     343                RTCStatsReport::OutboundRTPStreamStats stats;
     344                fillOutboundRTPStreamStats(stats, static_cast<const webrtc::RTCOutboundRTPStreamStats&>(rtcStats));
     345                report->addStats<IDLDictionary<RTCStatsReport::OutboundRTPStreamStats>>(WTFMove(stats));
     346                return;
     347            }
     348        }
    239349    });
    240350}
  • trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h

    r212338 r213108  
    3939class RTCRtpReceiver;
    4040class RTCSessionDescription;
    41 class RTCstatsReport;
     41class RTCStatsReport;
    4242class RealtimeOutgoingAudioSource;
    4343class RealtimeOutgoingVideoSource;
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r213105 r213108  
    193193                078E090B17D14CEE00420AA1 /* RTCPeerConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07221B7717CEC32700848E51 /* RTCPeerConnection.cpp */; };
    194194                078E090C17D14CEE00420AA1 /* RTCSessionDescription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07221B7A17CEC32700848E51 /* RTCSessionDescription.cpp */; };
    195                 078E090E17D14CEE00420AA1 /* RTCStatsReport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07221B8317CEC32700848E51 /* RTCStatsReport.cpp */; };
    196195                078E091217D14CEE00420AA1 /* UserMediaController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07221B8E17CEC32700848E51 /* UserMediaController.cpp */; };
    197196                078E091317D14CEE00420AA1 /* UserMediaRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07221B9017CEC32700848E51 /* UserMediaRequest.cpp */; };
     
    15671566                416E29A6102FA962007FC14E /* WorkerReportingProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 416E29A5102FA962007FC14E /* WorkerReportingProxy.h */; };
    15681567                416E6FE81BBD12DF000A3F64 /* ReadableStreamInternalsBuiltins.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B03D8061BB3110D00B764D9 /* ReadableStreamInternalsBuiltins.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1568                416E6FE81BBD12DF000A3F65 /* JSDOMBindingInternalsBuiltins.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B03D8061BB3110D00B764DA /* JSDOMBindingInternalsBuiltins.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15691569                416E6FE81BBD12DF000A6023 /* FetchInternalsBuiltins.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B03D8061BB3110D00B764B9 /* FetchInternalsBuiltins.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15701570                416E6FE81BBD12DF000A6033 /* StreamInternalsBuiltins.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B03D8061BB3110D00B764C9 /* StreamInternalsBuiltins.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    16021602                419BE7591BC7F42B00E1C85B /* WebCoreBuiltinNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 419BE7521BC7F3DB00E1C85B /* WebCoreBuiltinNames.h */; };
    16031603                41A1B00E1E526579007F3769 /* LibWebRTCProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41A1B00D1E52656E007F3769 /* LibWebRTCProvider.cpp */; };
     1604                41A1B01C1E54239B007F3769 /* JSDOMGuardedObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 41A1B01A1E542396007F3769 /* JSDOMGuardedObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1605                41A1B01D1E54239E007F3769 /* JSDOMGuardedObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41A1B01B1E542396007F3769 /* JSDOMGuardedObject.cpp */; };
    16041606                41A3D58E101C152D00316D07 /* DedicatedWorkerThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41A3D58C101C152D00316D07 /* DedicatedWorkerThread.cpp */; };
    16051607                41A3D58F101C152D00316D07 /* DedicatedWorkerThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 41A3D58D101C152D00316D07 /* DedicatedWorkerThread.h */; };
     
    16141616                41D015CA0F4B5C71004A662F /* ContentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 41D015C80F4B5C71004A662F /* ContentType.h */; };
    16151617                41D015CB0F4B5C71004A662F /* ContentType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D015C90F4B5C71004A662F /* ContentType.cpp */; };
     1618                41DEFCB51E56C1BD000D9E5F /* JSDOMMapLike.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41DEFCB31E56C1B9000D9E5F /* JSDOMMapLike.cpp */; };
     1619                41DEFCB61E56C1BD000D9E5F /* JSDOMMapLike.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DEFCB41E56C1B9000D9E5F /* JSDOMMapLike.h */; };
    16161620                41E1B1D00FF5986900576B3B /* AbstractWorker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41E1B1CA0FF5986900576B3B /* AbstractWorker.cpp */; };
    16171621                41E1B1D10FF5986900576B3B /* AbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E1B1CB0FF5986900576B3B /* AbstractWorker.h */; };
     
    72437247                07221B7B17CEC32700848E51 /* RTCSessionDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCSessionDescription.h; sourceTree = "<group>"; };
    72447248                07221B7C17CEC32700848E51 /* RTCSessionDescription.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCSessionDescription.idl; sourceTree = "<group>"; };
    7245                 07221B8317CEC32700848E51 /* RTCStatsReport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCStatsReport.cpp; sourceTree = "<group>"; };
    72467249                07221B8417CEC32700848E51 /* RTCStatsReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCStatsReport.h; sourceTree = "<group>"; };
    72477250                07221B8517CEC32700848E51 /* RTCStatsReport.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCStatsReport.idl; sourceTree = "<group>"; };
     
    89028905                41A023ED1A39DB7900F722DF /* WritableStream.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WritableStream.idl; sourceTree = "<group>"; };
    89038906                41A1B00D1E52656E007F3769 /* LibWebRTCProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCProvider.cpp; path = libwebrtc/LibWebRTCProvider.cpp; sourceTree = "<group>"; };
     8907                41A1B01A1E542396007F3769 /* JSDOMGuardedObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMGuardedObject.h; sourceTree = "<group>"; };
     8908                41A1B01B1E542396007F3769 /* JSDOMGuardedObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMGuardedObject.cpp; sourceTree = "<group>"; };
    89048909                41A3D58C101C152D00316D07 /* DedicatedWorkerThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DedicatedWorkerThread.cpp; sourceTree = "<group>"; };
    89058910                41A3D58D101C152D00316D07 /* DedicatedWorkerThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DedicatedWorkerThread.h; sourceTree = "<group>"; };
     
    89178922                41D015C90F4B5C71004A662F /* ContentType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentType.cpp; sourceTree = "<group>"; };
    89188923                41D51BB21E4E2E8100131A5B /* LibWebRTCAudioFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCAudioFormat.h; path = libwebrtc/LibWebRTCAudioFormat.h; sourceTree = "<group>"; };
     8924                41DEFCB21E56C1B9000D9E5F /* JSDOMBindingInternals.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSDOMBindingInternals.js; sourceTree = "<group>"; };
     8925                41DEFCB31E56C1B9000D9E5F /* JSDOMMapLike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMMapLike.cpp; sourceTree = "<group>"; };
     8926                41DEFCB41E56C1B9000D9E5F /* JSDOMMapLike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMMapLike.h; sourceTree = "<group>"; };
    89198927                41E1B1CA0FF5986900576B3B /* AbstractWorker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractWorker.cpp; sourceTree = "<group>"; };
    89208928                41E1B1CB0FF5986900576B3B /* AbstractWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractWorker.h; sourceTree = "<group>"; };
     
    1170311711                9908B0FD1BCAD07D00ED0F55 /* StreamInternalsBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StreamInternalsBuiltins.cpp; sourceTree = "<group>"; };
    1170411712                9908B0FD1BCAD07D00ED0F65 /* ReadableStreamInternalsBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadableStreamInternalsBuiltins.cpp; sourceTree = "<group>"; };
     11713                9908B0FD1BCAD07D00ED0F66 /* JSDOMBindingInternalsBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMBindingInternalsBuiltins.cpp; sourceTree = "<group>"; };
    1170511714                9908B0FD1BCAD07D00ED0F75 /* WritableStreamInternalsBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WritableStreamInternalsBuiltins.cpp; sourceTree = "<group>"; };
    1170611715                9908B0FD1BCAD07D00ED3F64 /* ReadableByteStreamInternalsBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadableByteStreamInternalsBuiltins.cpp; sourceTree = "<group>"; };
     
    1175011759                9B03D8061BB3110D00B764D8 /* ReadableStreamBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReadableStreamBuiltins.h; sourceTree = "<group>"; };
    1175111760                9B03D8061BB3110D00B764D9 /* ReadableStreamInternalsBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReadableStreamInternalsBuiltins.h; sourceTree = "<group>"; };
     11761                9B03D8061BB3110D00B764DA /* JSDOMBindingInternalsBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMBindingInternalsBuiltins.h; sourceTree = "<group>"; };
    1175211762                9B03D8061BB3110D00B764E8 /* WritableStreamBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritableStreamBuiltins.h; sourceTree = "<group>"; };
    1175311763                9B03D8061BB3110D00B764E9 /* WritableStreamInternalsBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritableStreamInternalsBuiltins.h; sourceTree = "<group>"; };
     
    1547315483                                07221B7B17CEC32700848E51 /* RTCSessionDescription.h */,
    1547415484                                07221B7C17CEC32700848E51 /* RTCSessionDescription.idl */,
    15475                                 07221B8317CEC32700848E51 /* RTCStatsReport.cpp */,
    1547615485                                07221B8417CEC32700848E51 /* RTCStatsReport.h */,
    1547715486                                07221B8517CEC32700848E51 /* RTCStatsReport.idl */,
     
    1800818017                                9908B0FD1BCAD07D00ED0F65 /* ReadableStreamInternalsBuiltins.cpp */,
    1800918018                                9B03D8061BB3110D00B764D9 /* ReadableStreamInternalsBuiltins.h */,
     18019                                9908B0FD1BCAD07D00ED0F66 /* JSDOMBindingInternalsBuiltins.cpp */,
     18020                                9B03D8061BB3110D00B764DA /* JSDOMBindingInternalsBuiltins.h */,
    1801018021                                5E2C43751BCF9A0B0001E2BC /* RTCPeerConnectionBuiltins.cpp */,
    1801118022                                5E2C43761BCF9A0B0001E2BC /* RTCPeerConnectionBuiltins.h */,
     
    2252622537                                93B70D4809EB0C7C009D8468 /* JSDOMBinding.h */,
    2252722538                                7C45C9C61E3E8ABA00AAB558 /* JSDOMBindingCaller.h */,
     22539                                41DEFCB21E56C1B9000D9E5F /* JSDOMBindingInternals.js */,
    2252822540                                7C45C9CA1E3E8D2E00AAB558 /* JSDOMBindingSecurity.cpp */,
    2252922541                                7C45C9C91E3E8CD700AAB558 /* JSDOMBindingSecurity.h */,
     
    2253422546                                7C2BDD3B17C7F98B0038FF15 /* JSDOMGlobalObjectTask.cpp */,
    2253522547                                7C2BDD3C17C7F98B0038FF15 /* JSDOMGlobalObjectTask.h */,
     22548                                41A1B01A1E542396007F3769 /* JSDOMGuardedObject.h */,
     22549                                41A1B01B1E542396007F3769 /* JSDOMGuardedObject.cpp */,
    2253622550                                4138F8551D253EEE001CB61E /* JSDOMIterator.cpp */,
    2253722551                                4138F8561D253EEE001CB61E /* JSDOMIterator.h */,
     22552                                41DEFCB31E56C1B9000D9E5F /* JSDOMMapLike.cpp */,
     22553                                41DEFCB41E56C1B9000D9E5F /* JSDOMMapLike.h */,
    2253822554                                E172AF8D1811BC3700FBADB9 /* JSDOMPromise.cpp */,
    2253922555                                E172AF8E1811BC3700FBADB9 /* JSDOMPromise.h */,
     
    2566825684                                26E944D91AC4B2DD007B85B5 /* CombinedURLFilters.h in Headers */,
    2566925685                                A584FE351864D5AF00843B10 /* CommandLineAPIHost.h in Headers */,
     25686                                41DEFCB61E56C1BD000D9E5F /* JSDOMMapLike.h in Headers */,
    2567025687                                A584FE2C1863870F00843B10 /* CommandLineAPIModule.h in Headers */,
    2567125688                                A584FE2618637DAB00843B10 /* CommandLineAPIModuleSource.h in Headers */,
     
    2734427361                                FFEFAB2A18380DA000514534 /* LineLayoutState.h in Headers */,
    2734527362                                FFDBC047183D27B700407109 /* LineWidth.h in Headers */,
     27363                                41A1B01C1E54239B007F3769 /* JSDOMGuardedObject.h in Headers */,
    2734627364                                A7AD2F880EC89D07008AB002 /* LinkHash.h in Headers */,
    2734727365                                CBA9DC0B1DF44DF40005675C /* LinkHeader.h in Headers */,
     
    2783027848                                416E6FE91BBD12E5000A6043 /* ReadableStreamBuiltins.h in Headers */,
    2783127849                                416E6FE81BBD12DF000A3F64 /* ReadableStreamInternalsBuiltins.h in Headers */,
     27850                                416E6FE81BBD12DF000A3F65 /* JSDOMBindingInternalsBuiltins.h in Headers */,
    2783227851                                FD31603C12B0267600C1A359 /* RealtimeAnalyser.h in Headers */,
    2783327852                                41103AAD1E39791000769F03 /* RealtimeIncomingAudioSource.h in Headers */,
     
    2975329772                                31288E740E3005D6003619AE /* CSSKeyframesRule.cpp in Sources */,
    2975429773                                BC772E16133162C2001EC9CE /* CSSLineBoxContainValue.cpp in Sources */,
     29774                                41DEFCB51E56C1BD000D9E5F /* JSDOMMapLike.cpp in Sources */,
    2975529775                                946D37491D6D06280077084F /* CSSMarkup.cpp in Sources */,
    2975629776                                A80E6CFC0A1989CA007FB8C5 /* CSSMediaRule.cpp in Sources */,
     
    3177831798                                078E090C17D14CEE00420AA1 /* RTCSessionDescription.cpp in Sources */,
    3177931799                                073BE34E17D180B2002BD431 /* RTCSessionDescriptionDescriptor.cpp in Sources */,
    31780                                 078E090E17D14CEE00420AA1 /* RTCStatsReport.cpp in Sources */,
    3178131800                                5E2C43671BCEE3770001E2BC /* RTCTrackEvent.cpp in Sources */,
    3178231801                                5824ABA21AE81116009074B7 /* RubyElement.cpp in Sources */,
     
    3191231931                                49E911CC0EF86D47009D0CAF /* SkewTransformOperation.cpp in Sources */,
    3191331932                                4150F9F212B6E0E70008C860 /* SliderThumbElement.cpp in Sources */,
     31933                                41A1B01D1E54239E007F3769 /* JSDOMGuardedObject.cpp in Sources */,
    3191431934                                9B532EA31BA928570038A827 /* SlotAssignment.cpp in Sources */,
    3191531935                                4B6FA6F70C39E4A100087011 /* SmartReplaceCF.cpp in Sources */,
  • trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp

    r212656 r213108  
    206206            visitor.append(constructor);
    207207
    208         for (auto& deferredPromise : thisObject->deferredPromises(locker))
    209             deferredPromise->visitAggregate(visitor);
     208        for (auto& guarded : thisObject->guardedObjects(locker))
     209            guarded->visitAggregate(visitor);
    210210    }
    211211
  • trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h

    r209570 r213108  
    3535namespace WebCore {
    3636
    37     class DeferredPromise;
     37    class DOMGuardedObject;
    3838    class Document;
    3939    class Event;
     
    4343    typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::Structure>> JSDOMStructureMap;
    4444    typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::JSObject>> JSDOMConstructorMap;
    45     typedef HashSet<DeferredPromise*> DeferredPromiseSet;
     45    typedef HashSet<DOMGuardedObject*> DOMGuardedObjectSet;
    4646
    4747    class WEBCORE_EXPORT JSDOMGlobalObject : public JSC::JSGlobalObject {
     
    5757    public:
    5858        Lock& gcLock() { return m_gcLock; }
    59        
     59
    6060        JSDOMStructureMap& structures(const AbstractLocker&) { return m_structures; }
    6161        JSDOMConstructorMap& constructors(const AbstractLocker&) { return m_constructors; }
    6262
    63         DeferredPromiseSet& deferredPromises(const AbstractLocker&) { return m_deferredPromises; }
     63        DOMGuardedObjectSet& guardedObjects(const AbstractLocker&) { return m_guardedObjects; }
    6464
    6565        ScriptExecutionContext* scriptExecutionContext() const;
     
    9595        JSDOMStructureMap m_structures;
    9696        JSDOMConstructorMap m_constructors;
    97         DeferredPromiseSet m_deferredPromises;
     97        DOMGuardedObjectSet m_guardedObjects;
    9898
    9999        Event* m_currentEvent;
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp

    r211454 r213108  
    3939namespace WebCore {
    4040
    41 DeferredPromise::DeferredPromise(JSDOMGlobalObject& globalObject, JSPromiseDeferred& promiseDeferred)
    42     : ActiveDOMCallback(globalObject.scriptExecutionContext())
    43     , m_deferred(&promiseDeferred)
    44     , m_globalObject(&globalObject)
    45 {
    46     auto locker = lockDuringMarking(globalObject.vm().heap, globalObject.gcLock());
    47     globalObject.vm().heap.writeBarrier(&globalObject, &promiseDeferred);
    48     globalObject.deferredPromises(locker).add(this);
    49 }
    50 
    51 DeferredPromise::~DeferredPromise()
    52 {
    53     clear();
    54 }
    55 
    56 void DeferredPromise::clear()
    57 {
    58     ASSERT(!m_deferred || m_globalObject);
    59     if (m_deferred && m_globalObject) {
    60         auto locker = lockDuringMarking(m_globalObject->vm().heap, m_globalObject->gcLock());
    61         m_globalObject->deferredPromises(locker).remove(this);
    62     }
    63     m_deferred.clear();
    64 }
    65 
    66 void DeferredPromise::contextDestroyed()
    67 {
    68     ActiveDOMCallback::contextDestroyed();
    69     clear();
    70 }
    71 
    7241JSC::JSValue DeferredPromise::promise() const
    7342{
    74     ASSERT(m_deferred);
    75     return m_deferred->promise();
     43    ASSERT(deferred());
     44    return deferred()->promise();
    7645}
    7746
     
    9867        return;
    9968
    100     ASSERT(m_deferred);
     69    ASSERT(deferred());
    10170    ASSERT(m_globalObject);
    10271    auto& state = *m_globalObject->globalExec();
     
    11079        return;
    11180
    112     ASSERT(m_deferred);
     81    ASSERT(deferred());
    11382    ASSERT(m_globalObject);
    11483    auto& state = *m_globalObject->globalExec();
     
    12291        return;
    12392
    124     ASSERT(m_deferred);
     93    ASSERT(deferred());
    12594    ASSERT(m_globalObject);
    12695    auto& state = *m_globalObject->globalExec();
     
    134103        return;
    135104
    136     ASSERT(m_deferred);
     105    ASSERT(deferred());
    137106    ASSERT(m_globalObject);
    138107    JSC::ExecState* state = m_globalObject->globalExec();
     
    146115        return;
    147116
    148     ASSERT(m_deferred);
     117    ASSERT(deferred());
    149118    ASSERT(m_globalObject);
    150119    JSC::ExecState* state = m_globalObject->globalExec();
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.h

    r211473 r213108  
    2626#pragma once
    2727
    28 #include "ActiveDOMCallback.h"
    2928#include "JSDOMConvert.h"
    30 #include <heap/StrongInlines.h>
     29#include "JSDOMGuardedObject.h"
    3130#include <runtime/JSPromiseDeferred.h>
    3231
    3332namespace WebCore {
    3433
    35 class DeferredPromise : public RefCounted<DeferredPromise>, public ActiveDOMCallback {
     34class DeferredPromise : public DOMGuarded<JSC::JSPromiseDeferred> {
    3635public:
    3736    static Ref<DeferredPromise> create(JSDOMGlobalObject& globalObject, JSC::JSPromiseDeferred& deferred)
     
    4039    }
    4140
    42     ~DeferredPromise();
    43 
    44     template<class IDLType>
     41    template<class IDLType>
    4542    void resolve(typename IDLType::ParameterType value)
    4643    {
    4744        if (isSuspended())
    4845            return;
    49         ASSERT(m_deferred);
    50         ASSERT(m_globalObject);
    51         JSC::ExecState* exec = m_globalObject->globalExec();
    52         JSC::JSLockHolder locker(exec);
    53         resolve(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value)));
     46        ASSERT(deferred());
     47        ASSERT(globalObject());
     48        JSC::ExecState* exec = globalObject()->globalExec();
     49        JSC::JSLockHolder locker(exec);
     50        resolve(*exec, toJS<IDLType>(*exec, *globalObject(), std::forward<typename IDLType::ParameterType>(value)));
    5451    }
    5552
     
    5855        if (isSuspended())
    5956            return;
    60         ASSERT(m_deferred);
    61         ASSERT(m_globalObject);
    62         JSC::ExecState* exec = m_globalObject->globalExec();
     57        ASSERT(deferred());
     58        ASSERT(globalObject());
     59        JSC::ExecState* exec = globalObject()->globalExec();
    6360        JSC::JSLockHolder locker(exec);
    6461        resolve(*exec, JSC::jsUndefined());
     
    7067        if (isSuspended())
    7168            return;
    72         ASSERT(m_deferred);
    73         ASSERT(m_globalObject);
    74         JSC::ExecState* exec = m_globalObject->globalExec();
    75         JSC::JSLockHolder locker(exec);
    76         resolve(*exec, toJSNewlyCreated<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value)));
    77     }
    78 
    79     template<class IDLType> 
     69        ASSERT(deferred());
     70        ASSERT(globalObject());
     71        JSC::ExecState* exec = globalObject()->globalExec();
     72        JSC::JSLockHolder locker(exec);
     73        resolve(*exec, toJSNewlyCreated<IDLType>(*exec, *globalObject(), std::forward<typename IDLType::ParameterType>(value)));
     74    }
     75
     76    template<class IDLType>
    8077    void reject(typename IDLType::ParameterType value)
    8178    {
    8279        if (isSuspended())
    8380            return;
    84         ASSERT(m_deferred);
    85         ASSERT(m_globalObject);
    86         JSC::ExecState* exec = m_globalObject->globalExec();
    87         JSC::JSLockHolder locker(exec);
    88         reject(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value)));
     81        ASSERT(deferred());
     82        ASSERT(globalObject());
     83        JSC::ExecState* exec = globalObject()->globalExec();
     84        JSC::JSLockHolder locker(exec);
     85        reject(*exec, toJS<IDLType>(*exec, *globalObject(), std::forward<typename IDLType::ParameterType>(value)));
    8986    }
    9087
     
    10097        if (isSuspended())
    10198            return;
    102         ASSERT(m_deferred);
    103         ASSERT(m_globalObject);
    104         JSC::ExecState* exec = m_globalObject->globalExec();
    105         JSC::JSLockHolder locker(exec);
    106         resolve(*exec, callback(*exec, *m_globalObject.get()));
     99        ASSERT(deferred());
     100        ASSERT(globalObject());
     101        JSC::ExecState* exec = globalObject()->globalExec();
     102        JSC::JSLockHolder locker(exec);
     103        resolve(*exec, callback(*exec, *globalObject()));
    107104    }
    108105
     
    112109        if (isSuspended())
    113110            return;
    114         ASSERT(m_deferred);
    115         ASSERT(m_globalObject);
    116         JSC::ExecState* exec = m_globalObject->globalExec();
    117         JSC::JSLockHolder locker(exec);
    118         reject(*exec, callback(*exec, *m_globalObject.get()));
     111        ASSERT(deferred());
     112        ASSERT(globalObject());
     113        JSC::ExecState* exec = globalObject()->globalExec();
     114        JSC::JSLockHolder locker(exec);
     115        reject(*exec, callback(*exec, *globalObject()));
    119116    }
    120117
    121118    JSC::JSValue promise() const;
    122119
    123     bool isSuspended() { return !m_deferred || !canInvokeCallback(); } // The wrapper world has gone away or active DOM objects have been suspended.
    124     JSDOMGlobalObject* globalObject() { return m_globalObject.get(); }
    125 
    126     void visitAggregate(JSC::SlotVisitor& visitor) { visitor.append(m_deferred); }
    127 
    128120private:
    129     DeferredPromise(JSDOMGlobalObject&, JSC::JSPromiseDeferred&);
    130 
    131     void clear();
    132     void contextDestroyed() override;
     121    DeferredPromise(JSDOMGlobalObject& globalObject, JSC::JSPromiseDeferred& deferred) : DOMGuarded<JSC::JSPromiseDeferred>(globalObject, deferred) { }
     122
     123    JSC::JSPromiseDeferred* deferred() const { return guarded(); }
    133124
    134125    void callFunction(JSC::ExecState&, JSC::JSValue function, JSC::JSValue resolution);
    135     void resolve(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->resolve(), resolution); }
    136     void reject(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->reject(), resolution); }
    137 
    138     JSC::Weak<JSC::JSPromiseDeferred> m_deferred;
    139     JSC::Weak<JSDOMGlobalObject> m_globalObject;
     126    void resolve(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, deferred()->resolve(), resolution); }
     127    void reject(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, deferred()->reject(), resolution); }
    140128};
    141129
  • trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h

    r212656 r213108  
    3636    macro(associatedReadableByteStreamController) \
    3737    macro(autoAllocateChunkSize) \
     38    macro(backingMap) \
    3839    macro(body) \
    3940    macro(byobRequest) \
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r212689 r213108  
    10651065
    10661066    $count += scalar @{$interface->iterable->functions} if $interface->iterable;
     1067    $count += scalar @{$interface->mapLike->functions} if $interface->mapLike;
    10671068    $count += scalar @{$interface->serializable->functions} if $interface->serializable;
    10681069
     
    22822283    return 0 if !$propertyCount;
    22832284
    2284     foreach my $attribute (@{$interface->attributes}) {
     2285    my @attributes = @{$interface->attributes};
     2286    push(@attributes, @{$interface->mapLike->attributes}) if $interface->mapLike;
     2287
     2288    foreach my $attribute (@attributes) {
    22852289        next if ($attribute->isStatic);
    22862290        next if AttributeShouldBeOnInstance($interface, $attribute) != $isInstance;
     
    23232327    my @functions = @{$interface->functions};
    23242328    push(@functions, @{$interface->iterable->functions}) if IsKeyValueIterableInterface($interface);
     2329    push(@functions, @{$interface->mapLike->functions}) if $interface->mapLike;
    23252330    push(@functions, @{$interface->serializable->functions}) if $interface->serializable;
    23262331    foreach my $function (@functions) {
     
    29892994{
    29902995    my ($interface) = @_;
    2991    
     2996
     2997    # FIXME: This should return 1 for maplike once we support them.
     2998    return 1 if $interface->mapLike;
     2999
    29923000    return 1 if $interface->iterable;
    29933001    if (GetIndexedGetterFunction($interface)) {
     
    29953003        return 1 if $lengthAttribute and $codeGenerator->IsIntegerType($lengthAttribute->type);
    29963004    }
    2997     # FIXME: This should return 1 for maplike and setlike once we support them.
    29983005    return 0;
    29993006}
     
    30413048    my @functions = @{$interface->functions};
    30423049    push(@functions, @{$interface->iterable->functions}) if IsKeyValueIterableInterface($interface);
     3050    push(@functions, @{$interface->mapLike->functions}) if $interface->mapLike;
    30433051    push(@functions, @{$interface->serializable->functions}) if $interface->serializable;
     3052
     3053    my @attributes = @{$interface->attributes};
     3054    push(@attributes, @{$interface->mapLike->attributes}) if $interface->mapLike;
    30443055
    30453056    my $numConstants = @{$interface->constants};
    30463057    my $numFunctions = @functions;
    3047     my $numAttributes = @{$interface->attributes};
     3058    my $numAttributes = @attributes;
    30483059
    30493060    if ($numFunctions > 0) {
     
    30913102        push(@implContent, "// Attributes\n\n");
    30923103
    3093         foreach my $attribute (@{$interface->attributes}) {
     3104        foreach my $attribute (@attributes) {
    30943105            next if $attribute->extendedAttributes->{ForwardDeclareInHeader};
    30953106            next if IsJSBuiltin($interface, $attribute);
     
    31053116            push(@implContent, "#endif\n") if $conditionalString;
    31063117        }
    3107        
     3118
    31083119        if (NeedsConstructorProperty($interface)) {
    31093120            my $getter = "js" . $interfaceName . "Constructor";
     
    33593370                my $functionName = GetFunctionName($interface, $className, @{$interface->iterable->functions}[0]);
    33603371                push(@implContent, "    putDirect(vm, vm.propertyNames->iteratorSymbol, JSFunction::create(vm, globalObject(), 0, ASCIILiteral(\"[Symbol.Iterator]\"), $functionName), DontEnum);\n");
     3372            } elsif ($interface->mapLike) {
     3373                push(@implContent, "    putDirect(vm, vm.propertyNames->iteratorSymbol, getDirect(vm, vm.propertyNames->builtinNames().valuesPublicName()), DontEnum);\n");
    33613374            } else {
    33623375                AddToImplIncludes("<builtins/BuiltinNames.h>");
     
    34343447        push(@implContent, "    putDirect(vm, vm.propertyNames->toPrimitiveSymbol, jsUndefined(), DontDelete | ReadOnly | DontEnum);\n");
    34353448    }
     3449    push(@implContent, "    synchronizeBackingMap(*globalObject()->globalExec(), *globalObject(), *this);\n") if $interface->mapLike;
    34363450
    34373451    # Support for RuntimeEnabled attributes on instances.
     
    35873601    $numAttributes = $numAttributes + 1 if NeedsConstructorProperty($interface);
    35883602    if ($numAttributes > 0) {
    3589         foreach my $attribute (@{$interface->attributes}) {
     3603        foreach my $attribute (@attributes) {
    35903604            next if IsJSBuiltin($interface, $attribute);
    35913605
     
    36963710                } elsif ($attribute->isStatic) {
    36973711                    $functionName = "${interfaceName}::${functionName}";
     3712                } elsif ($attribute->isMapLike) {
     3713                    my $ucPropertyName = $codeGenerator->WK_ucfirst($functionName);
     3714                    $functionName = "forward" . $codeGenerator->WK_ucfirst($functionName) . "ToMapLike";
     3715                    push(@arguments, "state");
     3716                    push(@arguments, "thisObject");
    36983717                } else {
    36993718                    $functionName = "impl.${functionName}";
     
    37023721                unshift(@arguments, @callWithArgs);
    37033722                my $jsType = NativeToJSValueUsingReferences($attribute, $interface, "${functionName}(" . join(", ", @arguments) . ")", "thisObject");
    3704                 push(@implContent, "    auto& impl = thisObject.wrapped();\n") if !$attribute->isStatic;
     3723                push(@implContent, "    auto& impl = thisObject.wrapped();\n") unless $attribute->isStatic or $attribute->isMapLike;
    37053724                push(@implContent, "    JSValue result = $jsType;\n");
    37063725
     
    37773796    }
    37783797
    3779     foreach my $attribute (@{$interface->attributes}) {
     3798    foreach my $attribute (@attributes) {
    37803799        if (!IsReadonly($attribute)) {
    37813800            next if IsJSBuiltin($interface, $attribute);
     
    39523971    if ($numFunctions > 0) {
    39533972        my $inAppleCopyright = 0;
    3954         foreach my $function (@{$interface->functions}) {
     3973        foreach my $function (@functions) {
    39553974            next if IsJSBuiltin($interface, $function);
     3975            next if $function->isIterable;
     3976            next if $function->isSerializer;
    39563977            if ($function->extendedAttributes->{AppleCopyright}) {
    39573978                if (!$inAppleCopyright) {
     
    40814102                    push(@implContent, "    return JSValue::encode(castedThis->" . $functionImplementationName . "(*state));\n");
    40824103                } else {
    4083                     push(@implContent, "    auto& impl = castedThis->wrapped();\n");
     4104                    push(@implContent, "    auto& impl = castedThis->wrapped();\n") unless $function->isMapLike;
    40844105
    40854106                    GenerateArgumentsCountCheck(\@implContent, $function, $interface);
     
    41714192    GenerateImplementationIterableFunctions($interface) if $interface->iterable;
    41724193    GenerateSerializerFunction($interface, $className) if $interface->serializable;
     4194    AddToImplIncludes("JSDOMMapLike.h") if $interface->mapLike;
    41734195
    41744196    if ($needsVisitChildren) {
     
    46534675    if ($implementedBy) {
    46544676        AddToImplIncludes("${implementedBy}.h", $conditional);
    4655         unshift(@arguments, "impl") if !$function->isStatic;
     4677        unshift(@arguments, "impl") unless $function->isStatic;
    46564678        $functionName = "WebCore::${implementedBy}::${functionImplementationName}";
    46574679    } elsif ($function->isStatic || $isConstructor) {
    46584680        $functionName = "${interfaceName}::${functionImplementationName}";
    4659     } else {
     4681    } elsif ($function->isMapLike) {
     4682        $functionName = "forward" . $codeGenerator->WK_ucfirst($function->name) . "ToMapLike";
     4683        push(@arguments, "*state");
     4684        push(@arguments, "*castedThis");
     4685     } else {
    46604686        $functionName = "impl.${functionImplementationName}";
    46614687    }
  • trunk/Source/WebCore/bindings/scripts/IDLParser.pm

    r212311 r213108  
    6161    functions => '@',    # List of 'IDLOperation'
    6262    anonymousFunctions => '@', # List of 'IDLOperation'
    63     attributes => '@',    # List of 'IDLAttribute'   
     63    attributes => '@',    # List of 'IDLAttribute'
    6464    constructors => '@', # Constructors, list of 'IDLOperation'
    6565    customConstructors => '@', # Custom constructors, list of 'IDLOperation'
     
    6868    isPartial => '$', # Used for partial interfaces
    6969    iterable => '$', # Used for iterable interfaces
     70    mapLike => '$', # Used for mapLike interfaces
    7071    serializable => '$', # Used for serializable interfaces
    7172    extendedAttributes => '$',
     
    8889    arguments => '@', # List of 'IDLArgument'
    8990    isStatic => '$',
     91    isIterable => '$',
     92    isSerializer => '$',
     93    isMapLike => '$',
    9094    specials => '@',
    9195    extendedAttributes => '$',
     
    98102    type => 'IDLType',
    99103    isStatic => '$',
     104    isMapLike => '$',
    100105    isStringifier => '$',
    101106    isReadOnly => '$',
     
    109114    valueType => 'IDLType',
    110115    functions => '@', # Iterable functions (entries, keys, values, [Symbol.Iterator], forEach)
     116    extendedAttributes => '$',
     117});
     118
     119# https://heycam.github.io/webidl/#es-maplike
     120struct( IDLMapLike => {
     121    isReadOnly => '$',
     122    keyType => 'IDLType',
     123    valueType => 'IDLType',
     124    attributes => '@', # MapLike attributes (size)
     125    functions => '@', # MapLike functions (entries, keys, values, forEach, get, has and if not readonly, delete, set and clear)
    111126    extendedAttributes => '$',
    112127});
     
    195210{
    196211    my $message = shift;
    197    
     212
    198213    my $mess = longmess();
    199214    print Dumper($mess);
     
    421436}
    422437
    423 my $nextAttribute_1 = '^(attribute|inherit|readonly)$';
     438my $nextAttribute_1 = '^(attribute|inherit)$';
    424439my $nextPrimitiveType_1 = '^(int|long|short|unsigned)$';
    425440my $nextPrimitiveType_2 = '^(double|float|unrestricted)$';
     
    437452my $nextDefinitions_1 = '^(callback|dictionary|enum|exception|interface|partial|typedef)$';
    438453my $nextExceptionMembers_1 = '^(\(|ByteString|DOMString|USVString|Date|\[|any|boolean|byte|const|double|float|long|object|octet|optional|sequence|short|unrestricted|unsigned)$';
    439 my $nextAttributeRest_1 = '^(attribute|readonly)$';
    440454my $nextInterfaceMembers_1 = '^(\(|ByteString|DOMString|USVString|Date|any|attribute|boolean|byte|const|creator|deleter|double|float|getter|inherit|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$';
    441455my $nextSingleType_1 = '^(ByteString|DOMString|USVString|Date|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned)$';
     
    11411155        return $self->parseSerializer($extendedAttributeList);
    11421156    }
     1157
    11431158    if ($next->value() =~ /$nextAttributeOrOperation_1/) {
    11441159        my $qualifier = $self->parseQualifier();
    1145         my $newDataNode = $self->parseAttributeOrOperationRest($extendedAttributeList);
     1160        my $isReadOnly = $self->parseReadOnly();
     1161        my $newDataNode = $self->parseAttributeOrOperationRest($extendedAttributeList, $isReadOnly);
    11461162        if (defined($newDataNode)) {
    11471163            $newDataNode->isStatic(1) if $qualifier eq "static";
     
    11501166        return $newDataNode;
    11511167    }
     1168    my $isReadOnly = $self->parseReadOnly();
     1169    $next = $self->nextToken();
    11521170    if ($next->value() =~ /$nextAttribute_1/) {
    1153         return $self->parseAttribute($extendedAttributeList);
     1171        return $self->parseAttribute($extendedAttributeList, $isReadOnly);
    11541172    }
    11551173    if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperation_2/) {
    1156         return $self->parseOperationOrIterator($extendedAttributeList);
     1174        return $self->parseOperationOrIterator($extendedAttributeList, $isReadOnly);
    11571175    }
    11581176    $self->assertUnexpectedToken($next->value(), __LINE__);
     
    11791197        $toJSONFunction->name("toJSON");
    11801198        $toJSONFunction->extendedAttributes($extendedAttributeList);
     1199        $toJSONFunction->isSerializer(1);
    11811200        push(@{$newDataNode->functions}, $toJSONFunction);
    11821201
     
    13161335    my $self = shift;
    13171336    my $extendedAttributeList = shift;
    1318 
    1319     my $next = $self->nextToken();
    1320     if ($next->value() =~ /$nextAttributeRest_1/) {
    1321         return $self->parseAttributeRest($extendedAttributeList);
     1337    my $isReadOnly = shift;
     1338
     1339    my $next = $self->nextToken();
     1340    if ($next->value() eq "attribute") {
     1341        return $self->parseAttributeRest($extendedAttributeList, $isReadOnly);
    13221342    }
    13231343    if ($next->value() eq ";") {
     
    13401360    my $self = shift;
    13411361    my $extendedAttributeList = shift;
     1362    my $isReadOnly = shift;
    13421363
    13431364    my $next = $self->nextToken();
    13441365    if ($next->value() =~ /$nextAttribute_1/) {
    13451366        $self->parseInherit();
    1346         return $self->parseAttributeRest($extendedAttributeList);
     1367        return $self->parseAttributeRest($extendedAttributeList, $isReadOnly);
    13471368    }
    13481369    $self->assertUnexpectedToken($next->value(), __LINE__);
     
    13531374    my $self = shift;
    13541375    my $extendedAttributeList = shift;
    1355 
    1356     my $next = $self->nextToken();
    1357     if ($next->value() =~ /$nextAttributeRest_1/) {
     1376    my $isReadOnly = shift;
     1377
     1378    my $next = $self->nextToken();
     1379    if ($next->value() eq "attribute") {
    13581380        my $newDataNode = IDLAttribute->new();
    1359         $newDataNode->isReadOnly($self->parseReadOnly());
     1381        $newDataNode->isReadOnly($isReadOnly);
    13601382
    13611383        $self->assertTokenValue($self->getToken(), "attribute", __LINE__);
    1362        
     1384
    13631385        my $type = $self->parseType();
    13641386        $newDataNode->type($type);
     
    14061428    my $self = shift;
    14071429    my $extendedAttributeList = shift;
     1430    my $isReadOnly = shift;
    14081431
    14091432    my $next = $self->nextToken();
     
    14131436    if ($next->value() eq "iterable") {
    14141437        return $self->parseIterableRest($extendedAttributeList);
     1438    }
     1439    if ($next->value() eq "maplike") {
     1440        return $self->parseMapLikeRest($extendedAttributeList, $isReadOnly);
    14151441    }
    14161442    if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) {
     
    15091535    my $extendedAttributeList = shift;
    15101536
    1511     my $symbolIteratorFunction = IDLOperation->new();
    1512     $symbolIteratorFunction->name("[Symbol.Iterator]");
    1513     $symbolIteratorFunction->extendedAttributes($extendedAttributeList);
    1514 
    1515     my $entriesFunction = IDLOperation->new();
    1516     $entriesFunction->name("entries");
    1517     $entriesFunction->extendedAttributes($extendedAttributeList);
    1518 
    1519     my $keysFunction = IDLOperation->new();
    1520     $keysFunction->name("keys");
    1521     $keysFunction->extendedAttributes($extendedAttributeList);
    1522 
    1523     my $valuesFunction = IDLOperation->new();
    1524     $valuesFunction->name("values");
    1525     $valuesFunction->extendedAttributes($extendedAttributeList);
    1526 
    1527     my $forEachFunction = IDLOperation->new();
    1528     $forEachFunction->name("forEach");
    1529     $forEachFunction->extendedAttributes($extendedAttributeList);
    1530     my $forEachArgument = IDLArgument->new();
    1531     $forEachArgument->name("callback");
    1532     $forEachArgument->type(makeSimpleType("any"));
    1533     push(@{$forEachFunction->arguments}, ($forEachArgument));
    1534 
    15351537    my $newDataNode = IDLIterable->new();
    15361538    $newDataNode->extendedAttributes($extendedAttributeList);
    1537     push(@{$newDataNode->functions}, $symbolIteratorFunction);
    1538     push(@{$newDataNode->functions}, $entriesFunction);
    1539     push(@{$newDataNode->functions}, $keysFunction);
    1540     push(@{$newDataNode->functions}, $valuesFunction);
    1541     push(@{$newDataNode->functions}, $forEachFunction);
    15421539
    15431540    $self->assertTokenValue($self->getToken(), "<", __LINE__);
     
    15571554    $self->assertTokenValue($self->getToken(), ">", __LINE__);
    15581555
     1556    my $symbolIteratorFunction = IDLOperation->new();
     1557    $symbolIteratorFunction->name("[Symbol.Iterator]");
     1558    $symbolIteratorFunction->extendedAttributes($extendedAttributeList);
     1559    $symbolIteratorFunction->isIterable(1);
     1560
     1561    my $entriesFunction = IDLOperation->new();
     1562    $entriesFunction->name("entries");
     1563    $entriesFunction->extendedAttributes($extendedAttributeList);
     1564    $entriesFunction->isIterable(1);
     1565
     1566    my $keysFunction = IDLOperation->new();
     1567    $keysFunction->name("keys");
     1568    $keysFunction->extendedAttributes($extendedAttributeList);
     1569    $keysFunction->isIterable(1);
     1570
     1571    my $valuesFunction = IDLOperation->new();
     1572    $valuesFunction->name("values");
     1573    $valuesFunction->extendedAttributes($extendedAttributeList);
     1574    $valuesFunction->isIterable(1);
     1575
     1576    my $forEachFunction = IDLOperation->new();
     1577    $forEachFunction->name("forEach");
     1578    $forEachFunction->extendedAttributes($extendedAttributeList);
     1579    $forEachFunction->isIterable(1);
     1580    my $forEachArgument = IDLArgument->new();
     1581    $forEachArgument->name("callback");
     1582    $forEachArgument->type(makeSimpleType("any"));
     1583    push(@{$forEachFunction->arguments}, ($forEachArgument));
     1584
     1585    push(@{$newDataNode->functions}, $symbolIteratorFunction);
     1586    push(@{$newDataNode->functions}, $entriesFunction);
     1587    push(@{$newDataNode->functions}, $keysFunction);
     1588    push(@{$newDataNode->functions}, $valuesFunction);
     1589    push(@{$newDataNode->functions}, $forEachFunction);
     1590
     1591    return $newDataNode;
     1592}
     1593
     1594sub parseMapLikeRest
     1595{
     1596    my $self = shift;
     1597    my $extendedAttributeList = shift;
     1598    my $isReadOnly = shift;
     1599
     1600    my $next = $self->nextToken();
     1601    if ($next->value() eq "maplike") {
     1602        $self->assertTokenValue($self->getToken(), "maplike", __LINE__);
     1603        my $mapLikeNode = $self->parseMapLikeProperties($extendedAttributeList, $isReadOnly);
     1604        $self->assertTokenValue($self->getToken(), ";", __LINE__);
     1605        return $mapLikeNode;
     1606    }
     1607    $self->assertUnexpectedToken($next->value(), __LINE__);
     1608}
     1609
     1610sub parseMapLikeProperties
     1611{
     1612    my $self = shift;
     1613    my $extendedAttributeList = shift;
     1614    my $isReadOnly = shift;
     1615
     1616    my $newDataNode = IDLMapLike->new();
     1617    $newDataNode->extendedAttributes($extendedAttributeList);
     1618    $newDataNode->isReadOnly($isReadOnly);
     1619
     1620    $self->assertTokenValue($self->getToken(), "<", __LINE__);
     1621    $newDataNode->keyType($self->parseType());
     1622    $self->assertTokenValue($self->getToken(), ",", __LINE__);
     1623    $newDataNode->valueType($self->parseType());
     1624    $self->assertTokenValue($self->getToken(), ">", __LINE__);
     1625
     1626    my $notEnumerableExtendedAttributeList = $extendedAttributeList;
     1627    $notEnumerableExtendedAttributeList->{NotEnumerable} = 1;
     1628
     1629    my $sizeAttribute = IDLAttribute->new();
     1630    $sizeAttribute->name("size");
     1631    $sizeAttribute->isMapLike(1);
     1632    $sizeAttribute->extendedAttributes($extendedAttributeList);
     1633    $sizeAttribute->isReadOnly(1);
     1634    $sizeAttribute->type(makeSimpleType("any"));
     1635    push(@{$newDataNode->attributes}, $sizeAttribute);
     1636
     1637    my $getFunction = IDLOperation->new();
     1638    $getFunction->name("get");
     1639    $getFunction->isMapLike(1);
     1640    my $getArgument = IDLArgument->new();
     1641    $getArgument->name("key");
     1642    $getArgument->type($newDataNode->keyType);
     1643    $getArgument->extendedAttributes($extendedAttributeList);
     1644    push(@{$getFunction->arguments}, ($getArgument));
     1645    $getFunction->extendedAttributes($notEnumerableExtendedAttributeList);
     1646    $getFunction->type(makeSimpleType("any"));
     1647
     1648    my $hasFunction = IDLOperation->new();
     1649    $hasFunction->name("has");
     1650    $hasFunction->isMapLike(1);
     1651    my $hasArgument = IDLArgument->new();
     1652    $hasArgument->name("key");
     1653    $hasArgument->type($newDataNode->keyType);
     1654    $hasArgument->extendedAttributes($extendedAttributeList);
     1655    push(@{$hasFunction->arguments}, ($hasArgument));
     1656    $hasFunction->extendedAttributes($notEnumerableExtendedAttributeList);
     1657    $hasFunction->type(makeSimpleType("any"));
     1658
     1659    my $entriesFunction = IDLOperation->new();
     1660    $entriesFunction->name("entries");
     1661    $entriesFunction->isMapLike(1);
     1662    $entriesFunction->extendedAttributes($notEnumerableExtendedAttributeList);
     1663    $entriesFunction->type(makeSimpleType("any"));
     1664
     1665    my $keysFunction = IDLOperation->new();
     1666    $keysFunction->name("keys");
     1667    $keysFunction->isMapLike(1);
     1668    $keysFunction->extendedAttributes($notEnumerableExtendedAttributeList);
     1669    $keysFunction->type(makeSimpleType("any"));
     1670
     1671    my $valuesFunction = IDLOperation->new();
     1672    $valuesFunction->name("values");
     1673    $valuesFunction->isMapLike(1);
     1674    $valuesFunction->extendedAttributes($extendedAttributeList);
     1675    $valuesFunction->extendedAttributes->{NotEnumerable} = 1;
     1676    $valuesFunction->type(makeSimpleType("any"));
     1677
     1678    my $forEachFunction = IDLOperation->new();
     1679    $forEachFunction->name("forEach");
     1680    $forEachFunction->isMapLike(1);
     1681    $forEachFunction->extendedAttributes({});
     1682    $forEachFunction->type(makeSimpleType("any"));
     1683    my $forEachArgument = IDLArgument->new();
     1684    $forEachArgument->name("callback");
     1685    $forEachArgument->type(makeSimpleType("any"));
     1686    $forEachArgument->extendedAttributes($extendedAttributeList);
     1687    push(@{$forEachFunction->arguments}, ($forEachArgument));
     1688
     1689    push(@{$newDataNode->functions}, $getFunction);
     1690    push(@{$newDataNode->functions}, $hasFunction);
     1691    push(@{$newDataNode->functions}, $entriesFunction);
     1692    push(@{$newDataNode->functions}, $keysFunction);
     1693    push(@{$newDataNode->functions}, $valuesFunction);
     1694    push(@{$newDataNode->functions}, $forEachFunction);
     1695
     1696    return $newDataNode if $isReadOnly;
     1697
     1698    my $addFunction = IDLOperation->new();
     1699    $addFunction->name("add");
     1700    $addFunction->isMapLike(1);
     1701    my $addArgument = IDLArgument->new();
     1702    $addArgument->name("key");
     1703    $addArgument->type($newDataNode->keyType);
     1704    $addArgument->extendedAttributes($extendedAttributeList);
     1705    push(@{$addFunction->arguments}, ($addArgument));
     1706    $addFunction->extendedAttributes($notEnumerableExtendedAttributeList);
     1707    $addFunction->type(makeSimpleType("any"));
     1708
     1709    my $clearFunction = IDLOperation->new();
     1710    $clearFunction->name("clear");
     1711    $clearFunction->isMapLike(1);
     1712    $clearFunction->extendedAttributes($notEnumerableExtendedAttributeList);
     1713    $clearFunction->type(makeSimpleType("void"));
     1714
     1715    my $deleteFunction = IDLOperation->new();
     1716    $deleteFunction->name("delete");
     1717    $deleteFunction->isMapLike(1);
     1718    my $deleteArgument = IDLArgument->new();
     1719    $deleteArgument->name("key");
     1720    $deleteArgument->type($newDataNode->keyType);
     1721    $deleteArgument->extendedAttributes($extendedAttributeList);
     1722    push(@{$deleteFunction->arguments}, ($deleteArgument));
     1723    $deleteFunction->extendedAttributes($notEnumerableExtendedAttributeList);
     1724    $deleteFunction->type(makeSimpleType("any"));
     1725
     1726    push(@{$newDataNode->functions}, $addFunction);
     1727    push(@{$newDataNode->functions}, $clearFunction);
     1728    push(@{$newDataNode->functions}, $deleteFunction);
     1729
    15591730    return $newDataNode;
    15601731}
     
    15711742        my $name = $self->parseOptionalIdentifier();
    15721743        $newDataNode->name(identifierRemoveNullablePrefix($name));
    1573        
     1744
    15741745        $self->assertTokenValue($self->getToken(), "(", $name, __LINE__);
    1575        
     1746
    15761747        push(@{$newDataNode->arguments}, @{$self->parseArgumentList()});
    1577        
     1748
    15781749        $self->assertTokenValue($self->getToken(), ")", __LINE__);
    15791750        $self->assertTokenValue($self->getToken(), ";", __LINE__);
    1580        
     1751
    15811752        $newDataNode->extendedAttributes($extendedAttributeList);
    15821753        return $newDataNode;
     
    23942565            next;
    23952566        }
     2567        if (ref($item) eq "IDLMapLike") {
     2568            $interface->mapLike($item);
     2569            next;
     2570        }
    23962571        if (ref($item) eq "IDLOperation") {
    23972572            if ($item->name eq "") {
Note: See TracChangeset for help on using the changeset viewer.