diff --git a/spec.bs b/spec.bs index 08ddabc42..cad944aa0 100644 --- a/spec.bs +++ b/spec.bs @@ -1779,14 +1779,22 @@ following steps. They return a failure if failing to fetch the script or wasm, o 1. Let |prevWinElement| be the [=sequence=]<{{PreviousWinElement}}> «|timeDelta|, |prevWinAdIDL|». 1. [=list/Append=] |prevWinElement| to |prevWins|. 1. [=map/Set=] |browserSignals|["{{BiddingBrowserSignals/prevWinsMs}}"] to |prevWins|. + 1. Let |metrics| be a new [=execution metrics=]. 1. Let |biddingScriptFetcher| be the result of [=creating a new script fetcher=] with |ig|'s [=interest group/bidding url=], and |settings|. 1. Let |biddingScript| be the result of [=waiting for script body from a fetcher=] given |biddingScriptFetcher|. + 1. [=Add a sample to an averager=] given |metrics|'s [=execution metrics/average code fetch + time=] and |biddingScriptFetcher|'s [=script fetcher/fetch duration=]. 1. If |biddingScript| is failure, return failure. 1. If |ig|'s [=interest group/bidding wasm helper url=] is not null: + 1. Let |wasmFetchStart| be |settings|'s [=environment settings object/current monotonic time=]. 1. Let |wasmModuleObject| be the result of [=fetching WebAssembly=] with |ig|'s [=interest group/bidding wasm helper url=] and |settings|. + 1. Let |wasmFetchDuration| be the [=duration from=] |wasmFetchStart| to + |settings|'s [=environment settings object/current monotonic time=], in milliseconds. + 1. [=Add a sample to an averager=] given |metrics|'s [=execution metrics/average code fetch + time=] and |wasmFetchDuration|. 1. If |wasmModuleObject| is not failure, then [=map/set=] |browserSignals|["{{BiddingBrowserSignals/wasmHelper}}"] to |wasmModuleObject|. 1. Otherwise, return failure. @@ -1810,7 +1818,7 @@ following steps. They return a failure if failing to fetch the script or wasm, o |crossOriginTrustedBiddingSignalsOrigin|. 1. [=map/Set=] |crossOriginTrustedBiddingSignalsOrigin|[|originKey|] to |trustedBiddingSignals|. 1. Return the result of [=evaluating a bidding script=] with |biddingScript|, |multiBidLimit|, - |ig|, |reportingContext|, |expectedCurrency|, |igGenerateBid|, |auctionSignals|, + |ig|, |reportingContext|, |metrics|, |expectedCurrency|, |igGenerateBid|, |auctionSignals|, |perBuyerSignals|, |sameOriginTrustedBiddingSignals|, |crossOriginTrustedBiddingSignals|, |browserSignals|, |directFromSellerSignalsForBuyer| and |perBuyerTimeout|. @@ -1964,6 +1972,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: 1. If |perBuyerExperimentGroupIds| is not null and |perBuyerExperimentGroupIds|[|buyer|] [=map/exists=], then set |buyerExperimentGroupId| to |perBuyerExperimentGroupIds|[|buyer|]. 1. Apply interest groups limits to prioritized list: + 1. Let |metrics| be the result of [=accessing per-participant metrics=] for |reportingContext|, + |buyer|, [=worklet function/generate-bid=]. 1. Let |buyerGroupLimit| be |allBuyersGroupLimit|. 1. Let |perBuyerGroupLimits| be |auctionConfig|'s [=auction config/per buyer group limits=]. @@ -1981,6 +1991,9 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: 1. [=map/For each=] slotSizeQueryParam → |perSignalsUrlGenerator| of |perSlotSizeQueryParam|: 1. [=map/For each=] joiningOrigin → |groups| of |perSignalsUrlGenerator|: 1. [=list/Remove=] from |groups| any [=interest group=] [=list/contained=] in |igs|. + 1. Set |metrics|'s [=per participant metrics/participating interest group count=] to + |metrics|'s [=per participant metrics/participating interest group count=] + [=list/ + size=] of |groups|. 1. Let |perBuyerSignals| be null. 1. If |auctionConfig|'s [=auction config/per buyer signals=] is not null and [=auction config/per buyer signals=][|buyer|] [=map/exists=], then set |perBuyerSignals| to @@ -2057,8 +2070,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: 1. If |optedInForRealTimeReporting| is true, then [=add a platform contribution=] with [=bidding script failure bucket=], |realTimeContributionsMap| and |buyer|. 1. [=iteration/Continue=]. - 1. Let (|bidsBatch|, |bidDebugReportInfo|, |realTimeContributions|, |paContributions|) be - |generateBidResult|. + 1. Let (|bidsBatch|, |bidDebugReportInfo|, |realTimeContributions|, |paContributions|, + |executionMetrics|) be |generateBidResult|. 1. Let |generateBidDuration| be the [=duration from=] |generateBidStartTime| to |settings|'s [=environment settings object/current monotonic time=], in milliseconds. 1. If |perBuyerCumulativeTimeout| is not null, decrement |perBuyerCumulativeTimeout| by @@ -2083,8 +2096,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: 1. Let |generateBidStartTime| be |settings|'s [=environment settings object/current monotonic time=]. 1. Set (|generatedBids|, |bidDebugReportInfo|, |realTimeContributions|, - |paContributions|) to the result of running [=generate potentially multiple bids=] - with |allTrustedBiddingSignals|, + |paContributions|, |executionMetrics|) to the result of running [=generate potentially + multiple bids=] with |allTrustedBiddingSignals|, |crossOriginTrustedBiddingSignalsOrigin|, |auctionSignals|, a [=map/clone=] of |browserSignals|, |perBuyerSignals|, |directFromSellerSignalsForBuyer|, |perBuyerTimeout|, |expectedCurrency|, 1 (for multiBidLimit), |kAnonRestrictedIG|, |reportingContext|, |auctionStartTime|, @@ -2102,7 +2115,7 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|: 1. [=Apply any component ads target to a bid=] given |generatedBid|. 1. [=list/Append=] |generatedBid| to |bidsToScore|. 1. [=Register bids for reporting=] given |bidsToScore|, |ig|, |bidDebugReportInfo|, - |paContributions|, and |reportingContext|. + |paContributions|, |executionMetrics|, and |reportingContext|. 1. If |auctionConfig|'s [=auction config/per buyer real time reporting config=][|buyer|] is "`default-local-reporting`", then [=insert entries to map=] given |realTimeContributionsMap|, |buyer|, and |realTimeContributions|. @@ -2354,21 +2367,32 @@ or "component-auction", a [=currency tag=] |componentAuctionExpectedCurrency|, a "`default-local-reporting`", then [=add a platform contribution=] with [=scoring script failure bucket=], |realTimeContributionsMap| and |seller|. 1. Return. +1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|, + |auctionConfig|'s [=auction config/seller=], [=worklet function/score-ad=]. +1. [=Add a sample to an averager=] given |metrics|'s [=per participant metrics/average code fetch + time=] and |decisionLogicFetcher|'s [=script fetcher/fetch duration=]. 1. Let « |scoreAdResult|, |debugWinReportUrl|, |debugLossReportUrl|, |realTimeContributions|, - |paContributions| » be the result of [=evaluating a scoring script=] with |decisionLogicScript|, - |adMetadata|, |bidValue|'s [=bid with currency/value=], |auctionConfig|, |reportingContext|, - |sameOriginTrustedScoringSignals|, |crossOriginTrustedScoringSignals|, |browserSignals|, - |directFromSellerSignalsForSeller|, and |auctionConfig|'s [=auction config/seller timeout=]. + |paContributions|, |executionMetrics| » be the result of [=evaluating a scoring script=] with + |decisionLogicScript|, |adMetadata|, |bidValue|'s [=bid with currency/value=], |auctionConfig|, + |reportingContext|, |sameOriginTrustedScoringSignals|, |crossOriginTrustedScoringSignals|, + |browserSignals|, |directFromSellerSignalsForSeller|, and |auctionConfig|'s [=auction config/ + seller timeout=]. +1. Set |metrics|'s [=per participant metrics/script executions attempted=] to |metrics|'s [=per + participant metrics/script executions attempted=] + 1. +1. If |executionMetrics|'s [=execution metrics/script timeout occurred=] is true, set |metrics|'s + [=per participant metrics/script timeouts occurred=] to |metrics|'s [=per participant metrics/ + script timeouts occurred=] + 1. 1. If |generatedBid|'s [=generated bid/for k-anon auction=] is true: Note: Non-k-anonymous bids do not participate in reporting (except for platform real-time contributions, and some special handling of private aggregation requests involving reject-reason); as it would be problematic to report a winner that didn't actually win. - 1. If |reportingContext|'s [=reporting context/debug reporting info=][|generatedBid|'s [=generated - bid/reporting id=]] does not [=map/exist=], set it to a new [=bid debug reporting info=]. + 1. Let |reportingId| be |generatedBid|'s [=generated bid/reporting id=]. + 1. If |reportingContext|'s [=reporting context/debug reporting info=][|reportingId|] does not + [=map/exist=], set it to a new [=bid debug reporting info=]. 1. Let |bidDebugReportInfo| be |reportingContext|'s [=reporting context/debug reporting info=] - [|generatedBid|'s [=generated bid/reporting id=]]. + [|reportingId|]. 1. If |auctionLevel| is "top-level-auction": 1. Set |bidDebugReportInfo|'s [=bid debug reporting info/top level seller debug loss report url=] to |debugLossReportUrl|. @@ -2384,8 +2408,11 @@ or "component-auction", a [=currency tag=] |componentAuctionExpectedCurrency|, a 1. If |auctionConfig|'s [=auction config/seller real time reporting config=] is "`default-local-reporting`", then [=insert entries to map=] given |realTimeContributionsMap|, |seller|, and |realTimeContributions|. - 1. [=Commit private aggregation contributions=] given |paContributions|, |generatedBid|'s - [=generated bid/reporting id=] and |reportingContext|. + 1. [=set/Insert=] |reportingId| into |reportingContext|'s [=reporting context/seller + participants=]. + 1. + 1. [=Commit private aggregation contributions=] given |paContributions|, |reportingId|, and + |reportingContext|. 1. Let |scoreAdOutput| be result of [=processing scoreAd output=] with |scoreAdResult|. 1. Return if any of the following conditions hold: * |scoreAdOutput| is failure; @@ -2890,17 +2917,25 @@ and a [=global object=] |global|: [=generated bid/interest group=], |igAd|, and null is true: 1. If |igAd|'s [=interest group ad/buyer and seller reporting ID=] is not null, [=map/set=] |browserSignals|["{{ReportingBrowserSignals/buyerAndSellerReportingId}}"] to it. + 1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|, + |config|'s [=auction config/seller=], [=worklet function/report-result=]. 1. Let |sellerReportingScriptFetcher| be the result of [=creating a new script fetcher=] with |config|'s [=auction config/decision logic url=] and |global|'s [=relevant settings object=]. 1. Let |sellerReportingScript| be the result of [=waiting for script body from a fetcher=] given |sellerReportingScriptFetcher|. - 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored, |paContributions| » be the - result of [=evaluating a reporting script=] with |sellerReportingScript|, "`reportResult`", - |reportingContext|, |config|'s [=auction config/seller=], |config|'s [=auction config/seller - Private Aggregation coordinator=], |config|'s [=auction config/config idl=]'s - {{AuctionAdConfig/reportingTimeout}}, and + 1. [=Add a sample to an averager=] given |metrics|'s [=per participant metrics/average code fetch + time=] and |sellerReportingScriptFetcher|'s [=script fetcher/fetch duration=]. + 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored, |paContributions|, + |executionMetrics| » be the result of [=evaluating a reporting script=] with + |sellerReportingScript|, [=worklet function/report-result=], |reportingContext|, + |config|'s [=auction config/seller=], |config|'s + [=auction config/seller Private Aggregation coordinator=], |config|'s [=auction config/ + config idl=]'s {{AuctionAdConfig/reportingTimeout}}, and « |config|'s [=auction config/config idl=], |browserSignals|, |directFromSellerSignals| ». - 1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]: + 1. Set |metrics|'s [=per participant metrics/script executions attempted=] to 1. + 1. If |executionMetrics|'s [=execution metrics/script timeout occurred=] is true, set |metrics|'s + [=per participant metrics/script timeouts occurred=] to 1. + 1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]: : [=reporting result/report url=] :: |reportUrl| : [=reporting result/reporting beacon map=] @@ -2955,6 +2990,8 @@ a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=] (TODO: noise and bucket this signal) 1. Let |ig| be |winner|'s [=generated bid/interest group=]. + 1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|, + |ig|'s [=interest group/owner=], [=worklet function/report-win=]. 1. Let |igAd| be the [=interest group ad=] from ig's [=interest group/ads=] whose [=interest group ad/render url=] is |winner|'s [=generated bid/ad descriptor=]'s [=ad descriptor/url=]. @@ -2990,17 +3027,23 @@ a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=] |winner|'s [=generated bid/interest group=]'s [=interest group/bidding url=] and |settings|. 1. Let |buyerReportingScript| be the result of [=waiting for script body from a fetcher=] given |buyerReportingScriptFetcher|. + 1. [=Add a sample to an averager=] given |metrics|'s [=per participant metrics/average code fetch + time=] and |buyerReportingScriptFetcher|'s [=script fetcher/fetch duration=]. 1. Let |reportFunctionName| be "`reportWin`". 1. If |winner|'s [=generated bid/provided as additional bid=] is true: 1. Set |reportFunctionName| be "`reportAdditionalBidWin`". - 1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap|, |paContributions| » be - the result of [=evaluating a reporting script=] with |buyerReportingScript|, "`reportWin`", - |reportingContext|, |ig|'s [=interest group/owner=], |ig|'s [=interest group/Private Aggregation - coordinator=], |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config - idl=]'s {{AuctionAdConfig/reportingTimeout}}, and + 1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap|, |paContributions|, + |executionMetrics| » be the result of [=evaluating a reporting script=] with + |buyerReportingScript|, [=worklet function/report-win=], |reportingContext|, |ig|'s + [=interest group/owner=], |ig|'s [=interest group/ + Private Aggregation coordinator=], |leadingBidInfo|'s [=leading bid info/auction config=]'s + [=auction config/config idl=]'s {{AuctionAdConfig/reportingTimeout}}, and « |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config idl=]'s {{AuctionAdConfig/auctionSignals}}, |perBuyerSignalsForBuyer|, |sellerSignals|, |reportWinBrowserSignals|, |directFromSellerSignals| ». + 1. Set |metrics|'s [=per participant metrics/script executions attempted=] to 1. + 1. If |executionMetrics|'s [=execution metrics/script timeout occurred=] is true, set |metrics|'s + [=per participant metrics/script timeouts occurred=] to 1. 1. [=Commit private aggregation contributions=] given |paContributions|, |winner|'s [=generated bid/reporting id=] and |reportingContext|. 1. Set |leadingBidInfo|'s [=leading bid info/buyer reporting result=] to a [=reporting result=] @@ -3626,8 +3669,30 @@ A reporting context is a [=struct=] with the following [=struct/items :: A [=reporting bid key=] or null, initially null. This can be null even if [=reporting context/ local leader info=] has a leader set, in case this context is for a component auction that lost at top-level. + : bidder participants + :: A [=set=] of [=reporting bid keys=], representing interest groups that got a chance to generate + bids for the auction. This will be empty in top-level auctions, as the relevant state will be + in the component auctions. + : seller participants + :: A [=set=] of [=reporting bid keys=], representing various `scoreAd()` executions. Note that + some of these may be based on bids that started as additional bids or from component auctions + run by Bidding and Auction services, and not interest groups, so this list may be quite + different from [=reporting context/bidder participants=]. + : participant metrics + :: A [=map=] from a pair ([=origin=], [=worklet function=]) to [=per participant metrics=]. +
+To access per-participant metrics given a [=reporting context=] |reportingContext|, +an [=origin=] |origin| and [=worklet function=] |workletFunction|: +1. Let |key| be (|origin|, |workletFunction|). +1. If |reportingContext|'s [=reporting context/participant metrics=][|key|] does not [=map/exist=], + set |reportingContext|'s [=reporting context/participant metrics=][|key|] to a new [=per participant + metrics=]. +1. Return |reportingContext|'s [=reporting context/participant metrics=][|key|]. + +
+ A reporting context map is a [=map=] from [=auction config=] to [=reporting context=]. Here the keys are configurations for auctions that actually produce bids (e.g. not the top-level auction in a multi-party auction). @@ -3649,8 +3714,8 @@ auction in a multi-party auction).
To register bids for reporting given a [=list=] of [=generated bids=] |generatedBids|, [=interest group=] |ig|, [=bid debug reporting info=] - |bidDebugReportInfo|, a [=Private Aggregation contributions=] |paContributions| and a [=reporting - context=] |reportingContext|: + |bidDebugReportInfo|, a [=Private Aggregation contributions=] |paContributions|, + [=execution metrics=] |executionMetrics| and a [=reporting context=] |reportingContext|: 1. Let |id| be a new [=reporting bid key=] with the following [=struct/items=]: : [=reporting bid key/context=] :: |reportingContext| @@ -3665,6 +3730,16 @@ auction in a multi-party auction). :: |ig|'s [=interest group/name=] 1. [=map/Set=] |reportingContext|'s [=reporting context/debug reporting info=][|id|] to |bidDebugReportInfo|. + 1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|, + |ig|'s [=interest group/owner=], [=worklet function/generate-bid=]. + 1. [=Merge samples to an averager=] given |metrics|'s [=per participant metrics/average code fetch + time=] and |executionMetrics|'s [=execution metrics/average code fetch time=]. + 1. Set |metrics|'s [=per participant metrics/script executions attempted=] to + |metrics|'s [=per participant metrics/participating interest group count=]. + 1. If |executionMetrics|'s [=execution metrics/script timeout occurred=] is true, set |metrics|'s + [=per participant metrics/script timeouts occurred=] to |metrics|'s [=per participant metrics/ + script timeouts occurred=] + 1. + 1. [=set/Insert=] |id| into |reportingContext|'s [=reporting context/bidder participants=]. 1. [=Commit private aggregation contributions=] given |paContributions|, |id| and |reportingContext|. 1. [=list/For each=] |generatedBid| of |generatedBids|: @@ -4061,6 +4136,16 @@ A signal base value is one of the following: Note: this mapping to an integer is defined in [=determine a signal's numeric value=]. +: "average-code-fetch-time" +:: The numeric value is the average time it took to fetch code resources (JavaScript or WebAssembly) + for this particular worklet function, for this participant. +: "participating-ig-count" +:: The numeric value is the number of interest groups for the buyer actually participating in the + auction, after considering prioritization and capabilities. +: "percent-scripts-timeout" +:: The numeric value is percentage of executions of this script that hit their individual timeout, + out of all executions that were expected to happen. +

On event contribution entry

@@ -4074,6 +4159,10 @@ An on event contribution entry is a [=struct=] with the following items: :: A [=debug scope=] : debug details :: A [=debug details=] or null (default null) +: worklet function +:: A [=worklet function=]. +: origin +:: The [=origin=] of the script that contributed the entry. @@ -4091,6 +4180,74 @@ A worklet function is one of the following: +
+To find corresponding bid and score phase function given a [=worklet function=] |fn|: + + 1.Switch on on |fn|: +
+ : [=worklet function/generate-bid=] + :: Return [=worklet function/generate-bid=]. + : [=worklet function/score-ad=] + :: Return [=worklet function/score-ad=]. + : [=worklet function/report-result=] + :: Return [=worklet function/score-ad=]. + : [=worklet function/report-win=] + :: Return [=worklet function/generate-bid=]. + +
+
+ +### Averager ### {#private-aggregation-averager} +An averager is a a [=struct=] with the following [=struct/items=]: +
+ : count + :: A {{long}}, initially 0. + : sum + :: A {{double}}, initially 0. +
+ +
+To add a sample to an averager given an [=averager=] |averager|, a {{double}} |sample|: +1. Set |averager|'s [=averager/count=] to |averager|'s [=averager/count=] + 1. +1. Set |averager|'s [=averager/sum=] to |averager|'s [=averager/sum=] + |sample|. + +
+ +
+To merge samples to an averager given [=averagers=] |dest| and |source|: +1. Set |dest|'s [=averager/count=] to |dest|'s [=averager/count=] + |source|'s [averager/count=]. +1. Set |dest|'s [=averager/sum=] to |dest|'s [=averager/sum=] + |source|'s [averager/sum=]. + +
+ +
+To get the value to report from an averager given an [=averager=] |averager|: +1. If |averager|'s [=averager/count=] = 0, return 0. +1. Return |averager|'s [=averager/sum=] / [=averager/count=]. + +
+ +### Metrics structures ### {#private-aggregation-metrics-structures} +An execution metrics is a [=struct=] with the following [=struct/items=]: +
+ : average code fetch time + :: An [=averager=]. + : script timeout occurred + :: A [=boolean=], initially false. +
+ +A per participant metrics is a [=struct=] with the following [=struct/items=]: +
+ : participating interest group count + :: A {{long}}, initially 0. + : average code fetch time + :: An [=averager=]. + : script timeouts occurred + :: A {{long}}, initially 0. + : script executions attempted + :: A {{long}}, initially 0. +
+

Private Aggregation contributions

Private Aggregation contributions is a [=map=] from [=string=] to a [=list=] of [=on event contribution entries=]. @@ -4099,9 +4256,11 @@ contribution entries=].
To prepare for private aggregation given a -{{InterestGroupScriptRunnerGlobalScope}} |global|, a [=reporting context=] |reportingContext|, -and [=origins=] |origin| and |aggregationCoordinator|: +{{InterestGroupScriptRunnerGlobalScope}} |global|, a [=worklet function=] |workletFunction|, +a [=reporting context=] |reportingContext|, and [=origins=] |origin| and |aggregationCoordinator|: 1. Let |debugScope| be a new [=debug scope=]. +1. Set |global|'s [=InterestGroupScriptRunnerGlobalScope/worklet function=] to |workletFunction|. +1. Set |global|'s [=InterestGroupScriptRunnerGlobalScope/origin=] to |origin|. 1. Set |global|'s [=InterestGroupScriptRunnerGlobalScope/private aggregation=] to a new [=PrivateAggregation=] with the following [=struct/items=]: : allowed to use @@ -4191,14 +4350,26 @@ an [=auction config=] |auctionConfig| and a [=reporting context=] |reportingCont 1. If |auctionConfig|'s [=auction config/aborted=] is true, return. 1. Let |winnerId| be |reportingContext|'s [=reporting context/winner reporting id=] 1. Let |leadingBidInfo| be |reportingContext|'s [=reporting context/local leader info=]. +1. Let |bidderOnceRep| be null. +1. If |reportingContext|'s [=reporting context/bidder participants=] [=set/is not empty=], + set |bidderOnceRep| to a random [=set/item=] of [=reporting context/bidder participants=]. +1. Let |sellerOnceRep| be null. +1. If |reportingContext|'s [=reporting context/seller participants=] [=set/is not empty=], + set |sellerOnceRep| to a random [=set/item=] of [=reporting context/seller participants=]. 1. [=map/For each=] (|bidId|, |event|) → |contributions| of |reportingContext|'s [=reporting context/private aggregation on event contributions=]: 1. If |event| is "`reserved.win`" or does not [=string/start with=] "`reserved.`": 1. If |bidId| is not |winnerId|, [=iteration/continue=]. 1. If |event| is "`reserved.loss`" and |bidId| is |winnerId|, [=iteration/continue=]. 1. [=list/For each=] |onEventEntry| of |contributions|: + 1. If |event| is "`reserved.once`": + 1. If |onEventEntry|'s [=on event contribution entry/worklet function=] is [=worklet function/ + generate-bid=]: + 1. If |bidId| ≠ |bidderOnceRep|, [=iteration/continue=]. + 1. Otherwise: + 1. If |bidId| ≠ |sellerOnceRep|, [=iteration/continue=]. 1. Let |filledInContribution| be the result of [=filling in the contribution=] given - |onEventEntry|'s [=on event contribution entry/contribution=] and |leadingBidInfo|. + |reportingContext|, |onEventEntry| and |leadingBidInfo|. Issue: Once WICG/turtledove#627 is resolved, align 'filling in' logic with `forDebuggingOnly`. @@ -4310,15 +4481,18 @@ an [=auction config=] |auctionConfig| and a [=reporting context=] |reportingCont
-To fill in the contribution given a {{PAExtendedHistogramContribution}} |contribution| -and a [=leading bid info=] |leadingBidInfo|, perform the following steps. They return a -{{PAHistogramContribution}}: +To fill in the contribution given a [=reporting context=] |reportingContext|, +an [=on event contribution entry=] |onEventEntry| and a [=leading bid info=] |leadingBidInfo|, +perform the following steps. They return a {{PAHistogramContribution}}: +1. Let |contribution| be |onEventEntry|'s [=on event contribution entry/contribution=]. 1. Let |bucket| be |contribution|["{{PAExtendedHistogramContribution/bucket}}"]. 1. If |bucket| is a {{PASignalValue}}, set |bucket| to the result of [=filling - in the signal value=] given |bucket|, 2128−1 and |leadingBidInfo|. + in the signal value=] given |reportingContext|, |onEventEntry|, |bucket|, 2128−1 + and |leadingBidInfo|. 1. Let |value| be |contribution|["{{PAExtendedHistogramContribution/value}}"]. 1. If |value| is a {{PASignalValue}}, set |value| to the result of [=filling in - the signal value=] given |value|, 231−1 and |leadingBidInfo|. + the signal value=] given |reportingContext|, |onEventEntry|, |value|, 231−1 and + |leadingBidInfo|. 1. Let |filledInContribution| be a new {{PAHistogramContribution}} with the items: : {{PAHistogramContribution/bucket}} @@ -4332,13 +4506,15 @@ and a [=leading bid info=] |leadingBidInfo|, perform the following steps. They r
-To fill in the signal value given a {{PASignalValue}} |value|, an +To fill in the signal value given a [=reporting context=] |reportingContext|, +an [=on event contribution entry=] |onEventEntry|, a {{PASignalValue}} |value|, an integer |maxAllowed| and a [=leading bid info=] |leadingBidInfo|, perform the following steps. They return an integer. 1. [=Assert=]: |value|["{{PASignalValue/baseValue}}"] is a valid [=signal base value=]. 1. Let |returnValue| be the result of [=determining a signal's numeric value=] - given |value|["{{PASignalValue/baseValue}}"] and |leadingBidInfo|. + given |reportingContext|, |onEventEntry|, |value|["{{PASignalValue/baseValue}}"] and + |leadingBidInfo|. 1. If |value|["{{PASignalValue/scale}}"] [=map/exists=], set |returnValue| to the result of multiplying |value|["{{PASignalValue/scale}}"] with |returnValue|. @@ -4353,9 +4529,17 @@ They return an integer.
-To determine a signal's numeric value given a [=signal base value=] +To determine a signal's numeric value given a [=reporting context=] |reportingContext|, +an [=on event contribution entry=] |onEventEntry|, a [=signal base value=] |signalBaseValue| and a [=leading bid info=] |leadingBidInfo|, perform the following steps. They return a {{double}}. +1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|, + |onEventEntry|'s [=on event contribution entry/origin=], [=on event contribution entry/ + worklet function=]. +1. Let |bidAndScoreMetrics| be the result of [=access per-participant metrics=] given + |reportingContext|, |onEventEntry|'s [=on event contribution entry/origin=], and the result of + [=find corresponding bid and score phase function=] given [=on event contribution entry/worklet + function=]. 1. If |signalBaseValue| is "[=signal base value/winning-bid=]": 1. If |leadingBidInfo|'s [=leading bid info/leading bid=] is null, return 0. 1. Otherwise, return |leadingBidInfo|'s [=leading bid info/leading bid=]'s [=generated bid/bid=]. @@ -4418,6 +4602,25 @@ They return a {{double}}. Issue: Verify handling when the bid was not rejected. +1. If |signalBaseValue| is "[=signal base value/average-code-fetch-time=]": + 1. Return the result of [=getting the value to report from an averager=] given |metrics|'s [=per + participant metrics/average code fetch time=]. +1. If |signalBaseValue| is "[=signal base value/participating-ig-count=]": + 1. Return |bidAndScoreMetrics|'s [=per participant metrics/participating interest group count=]. +1. If |signalBaseValue| is "[=signal base value/percent-scripts-timeout=]": + 1. Return the result of [=computing a percentage metric=] given |metrics|'s [=per participant + metrics/script timeouts occurred=] and |metrics|'s [=per participant metrics/script executions + attempted=]. + +
+ +
+To compute a percentage metric given {{long}}s |numerator| and |denominator|: +1. If |denominator| is 0, return 0. +1. Let |result| be 100.0 * |numerator| / |denominator|, performing the computation with + {{double}}s. +1. If |result| > 110.0, set |result| to 110.0 +1. Return |result|.
@@ -5298,6 +5501,7 @@ of the following global objects:
To evaluate a bidding script given a [=string=] |script|, an {{unsigned short}} |multiBidLimit|, an [=interest group=] |ig|, a [=reporting context=] |reportingContext|, + an [=execution metrics=] |executionMetrics|, a [=currency tag=] |expectedCurrency|, a {{GenerateBidInterestGroup}} |igGenerateBid|, a [=string=]-or-null |auctionSignals|, a [=string=]-or-null |perBuyerSignals|, an [=ordered map=]-or-null |sameOriginTrustedBiddingSignals|, an [=ordered map=]-or-null @@ -5318,8 +5522,9 @@ of the following global objects: [=InterestGroupBiddingScriptRunnerGlobalScope/group has ad components=] to true if |ig|'s [=interest group/ad components=] is not null, or false otherwise. 1. Set |global|'s [=InterestGroupBiddingScriptRunnerGlobalScope/expected currency=] to |expectedCurrency|. - 1. [=Prepare for private aggregation=] given |global|, |reportingContext|, |ig|'s [=interest - group/owner=] and |ig|'s [=interest group/Private Aggregation coordinator=]. + 1. [=Prepare for private aggregation=] given |global|, [=worklet function/generate-bid=], + |reportingContext|, |ig|'s [=interest group/owner=] and |ig|'s [=interest group/Private + Aggregation coordinator=]. 1. Let |isComponentAuction| be true if |browserSignals|["{{BiddingBrowserSignals/topLevelSeller}}"] is not null, or false otherwise. 1. Set |global|'s [=InterestGroupBiddingScriptRunnerGlobalScope/is component auction=] to @@ -5340,7 +5545,8 @@ of the following global objects: 1. Let |crossOriginTrustedBiddingSignalsJS| be |crossOriginTrustedBiddingSignals| [=converted to ECMAScript values=]. 1. Let |startTime| be |settings|'s [=environment settings object/current monotonic time=]. - 1. Let |result| be the result of [=evaluating a script=] with |realm|, |script|, "`generateBid`", + 1. Let (|result|, |executionMetrics|'s [=execution metrics/script timeout occurred=]) be the + result of [=evaluating a script=] with |realm|, |script|, "`generateBid`", « |igJS|, |auctionSignalsJS|, |perBuyerSignalsJS|, |sameOriginTrustedBiddingSignalsJS|, |browserSignalsJS|, |directFromSellerSignalsJS|, |crossOriginTrustedBiddingSignalsJS| », and |timeout|. @@ -5395,7 +5601,7 @@ of the following global objects: 1. Let |paContributions| be the result of [=extracting private aggregation contributions=] given |global|. 1. Return a [=tuple=] (|generatedBids|, |bidDebugReportInfo|, |realTimeContributions|, - |paContributions|). + |paContributions|, |executionMetrics|).
@@ -5410,9 +5616,9 @@ of the following global objects: {{InterestGroupScoringScriptRunnerGlobalScope}}. 1. Let |global| be |realm|'s [=realm/global object=]. 1. Let |settings| be |realm|'s [=realm/settings object=]. - 1. [=Prepare for private aggregation=] given |global|, |reportingContext|, |auctionConfig|'s - [=auction config/seller=] and |auctionConfig|'s [=auction config/seller Private Aggregation - coordinator=]. + 1. [=Prepare for private aggregation=] given |global|, [=worklet function/score-ad=], + |reportingContext|, |auctionConfig|'s [=auction config/seller=] and |auctionConfig|'s + [=auction config/seller Private Aggregation coordinator=]. 1. Let |browserSignalsJS| be |browserSignals| [=converted to ECMAScript values=]. 1. Let |auctionConfigJS| be |auctionConfig|'s [=auction config/config idl=] [=converted to ECMAScript values=]. @@ -5423,7 +5629,9 @@ of the following global objects: 1. Let |directFromSellerSignalsJs| be |directFromSellerSignalsForSeller| [=converted to ECMAScript values=]. 1. Let |startTime| be |settings|'s [=environment settings object/current monotonic time=]. - 1. Let |scoreAdResult| be the result of [=evaluating a script=] with |realm|, |script|, "`scoreAd`", + 1. Let |executionMetrics| be a new [=execution metrics=]. + 1. Let (|scoreAdResult|, |executionMetrics|'s [=execution metrics/script timeout occurred=]) be + the result of [=evaluating a script=] with |realm|, |script|, "`scoreAd`", «|adMetadata|, |bidValue|, |auctionConfigJS|, |sameOriginTrustedScoringSignalsJS|, |browserSignalsJS|, |directFromSellerSignalsJs|, |crossOriginTrustedScoringSignalsJS|», and |timeout|. @@ -5445,25 +5653,29 @@ of the following global objects: 1. Let |paContributions| be the result of [=extracting private aggregation contributions=] given |global|. 1. Return « |scoreAdResult|, |debugWinReportUrl|, |debugLossReportUrl|, |realTimeContributions|, - |paContributions| ». + |paContributions|, |executionMetrics| ».
- To evaluate a reporting script given a [=string=] |script|, a [=string=] - |functionName|, a [=reporting context=] |reportingContext|, an [=origin=] |origin|, an - [=origin=] |privateAggregationCoordinator|, an integer millisecond [=duration=] |timeout|, - and a [=list=] of arguments |arguments|: + To evaluate a reporting script given a [=string=] |script|, a [=worklet function=] + |function|, a [=reporting context=] |reportingContext|, an [=origin=] |origin|, an [=origin=] + |privateAggregationCoordinator|, an integer millisecond [=duration=] |timeout|, and a [=list=] + of arguments |arguments|: 1. Let |realm| be the result of [=creating a new script runner realm=] given {{InterestGroupReportingScriptRunnerGlobalScope}}. 1. Let |global| be |realm|'s [=realm/global object=]. - 1. [=Prepare for private aggregation=] given |global|, |reportingContext|, |origin|, and - |privateAggregationCoordinator|. + 1. Let |functionName| be `"reportWin"`. + 1. If |function| is [=worklet function/report-result=], set |functionName| to `"reportResult"`. + 1. [=Prepare for private aggregation=] given |global|, |function|, |reportingContext|, |origin|, + and |privateAggregationCoordinator|. 1. Let |argumentsJS| be the result of [=converting a Web IDL arguments list to an ECMAScript arguments list|converting=] |arguments| to an ECMAScript arguments list. If this [=exception/throws=] an exception, return « "null", null, null, null ». - 1. Let |result| be the result of [=evaluating a script=] with |realm|, |script|, - |functionName|, |argumentsJS|, and |timeout|. + 1. Let |executionMetrics| be a new [=execution metrics=]. + 1. Let (|result|, |executionMetrics|'s [=execution metrics/script timeout occurred=]) be the + result of [=evaluating a script=] with |realm|, |script|, |functionName|, |argumentsJS|, + and |timeout|. 1. If |result| is an [=ECMAScript/abrupt completion=], return « "null", null, null, null ». 1. Let |resultJSON| be "null". 1. If |functionName| is "`reportResult`", then set |resultJSON| to the result of @@ -5480,20 +5692,23 @@ of the following global objects: |global|. 1. Return « |resultJSON|, |reportURL|, |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=], |macroMap|, - |paContributions| ». + |paContributions|, |executionMetrics| ».
To evaluate a script with a [=ECMAScript/realm=] |realm|, [=string=] |script|, [=string=] |functionName|, a [=list=] |arguments|, and an integer millisecond [=duration=] |timeout|, run these steps. - They return a [=ECMAScript/Completion Record=], which is either an [=ECMAScript/abrupt completion=] (in - the case of a parse failure or execution error), or a [=ECMAScript/normal completion=] populated with the - [=ECMAScript/ECMAScript language value=] result of invoking |functionName|. + They return a tuple of a [=ECMAScript/Completion Record=], which is either an [=ECMAScript/abrupt + completion=] (in the case of a parse failure or execution error), or a [=ECMAScript/normal + completion=] populated with the [=ECMAScript/ECMAScript language value=] result of invoking + |functionName|, and a [=boolean=] stating whether the script was interrupted due to reaching + |timeout|. 1. [=Assert=] that these steps are running [=in parallel=]. - 1. If |timeout| ≤ 0, [=immediately=] interrupt the execution and set |finalCompletion| to a - new [=ECMAScript/throw completion=] given null. + 1. If |timeout| ≤ 0, return (new [=ECMAScript/throw completion=] given null, true). + + 1. Let |timeoutOccurred| be false. 1. Let |global| be |realm|'s [=realm/global object=], and run these steps in |realm|'s [=realm/agent=]: @@ -5524,8 +5739,8 @@ of the following global objects: |arguments|)). In |timeout| milliseconds, if the invocation of [$Call$] has not completed, - [=immediately=] interrupt the execution and set |finalCompletion| to a new - [=ECMAScript/throw completion=] given null. + [=immediately=] interrupt the execution, set |finalCompletion| to a new + [=ECMAScript/throw completion=] given null, and set |timeoutOccurred| to true. 1. Return: at this point |finalCompletion| will be set to a [=ECMAScript/Completion Record=]. @@ -5534,7 +5749,7 @@ of the following global objects: execution context|running JavaScript execution context=], and remove it from the [=ECMAScript/execution context stack|JavaScript execution context stack=]. - 1. Return |finalCompletion|. + 1. Return (|finalCompletion|, timeoutOccurred).
## Global scopes ## {#global-scopes} @@ -5576,6 +5791,12 @@ Each {{InterestGroupScriptRunnerGlobalScope}} has a :: Null, or a [=PrivateAggregation=]. Initially null. : on event contribution map :: A [=map=] from [=string=] to a [=list=] of [=on event contribution entries=]. + : worklet function + :: A [=worklet function=]. Affects some + [Private Aggregation API](https://github.com/patcg-individual-drafts/private-aggregation-api) + functionality. + : origin + :: The [=origin=] of the script being executed.
@@ -5589,16 +5810,21 @@ The privateAggregation The contributeToHistogramOnEvent(DOMString event, PAExtendedHistogramContribution contribution) method steps are: +1. Let |global| be [=this=]'s [=relevant global object=]. +1. Let |function| be |global|'s [=InterestGroupScriptRunnerGlobalScope/worklet function=]. +1. Let |origin| be |global|'s [=InterestGroupScriptRunnerGlobalScope/origin=]. 1. If [=this=]'s allowed to use is false, [=exception/throw=] a {{TypeError}}. 1. Let |scopingDetails| be [=this=]'s scoping details 1. If |event| [=string/starts with=] "`reserved.`" and « "`reserved.always`", - "`reserved.loss`", "`reserved.win`" » does not [=list/contain=] |event|, + "`reserved.loss`", "`reserved.win`", "`reserved.once`" » does not [=list/contain=] |event|, return. Note: No error is thrown to allow forward compatibility if additional reserved event types are added later. +1. If |event| is "`reserved.once`" and |function| is [=worklet function/report-result=] or + [=worklet function/report-win=], [=exception/throw=] a {{TypeError}}. 1. Let |bucket| be |contribution|["{{PAExtendedHistogramContribution/bucket}}"]. 1. If |bucket| is a {{PASignalValue}}: 1. If |bucket|["{{PASignalValue/baseValue}}"] is not a valid [=signal base @@ -5644,8 +5870,10 @@ event, PAExtendedHistogramContribution contribution) method steps are: : [=on event contribution entry/debug scope=] :: The result of running |scopingDetails|' get debug scope steps. - -1. Let |global| be [=this=]'s [=relevant global object=]. + : [=on event contribution entry/worklet function=] + :: |function| + : [=on event contribution entry/origin=] + :: |origin| 1. Let |onEventContributionMap| be |global|'s [=InterestGroupScriptRunnerGlobalScope/on event contribution map=]. 1. If |onEventContributionMap|[|event|] does not [=map/exist=], set @@ -7819,6 +8047,8 @@ headers. It's a [=struct=] with the following [=struct/items=]: : origins authorized for cross origin trusted signals :: A [=list=] of [=origins=] or null. Initially null. Parsed value of [:Ad-Auction-Allow-Trusted-Scoring-Signals-From:]. + : fetch duration + :: A [=duration=] in milliseconds, denoting how long it took the fetch to complete.
@@ -7896,6 +8126,8 @@ a [=script fetcher=] |fetcher|: Issue: Stop using "`no-cors`" mode where possible (WICG/turtledove#667). + + 1. Let |fetchStart| be |settings|'s [=environment settings object/current monotonic time=]. 1. Let |fetchController| be the result of [=fetching=] |request| with [=fetch/useParallelQueue=] set to true, and [=fetch/processResponse=] set to the following steps given a [=response=] |response|: @@ -7903,6 +8135,8 @@ a [=script fetcher=] |fetcher|: 1. [=fetch controller/Abort=] |fetchController|. 1. Set |fetcher|'s [=script fetcher/origins authorized for cross origin trusted signals=] to an empty [=list=] of [=origins=]. + 1. Set |fetcher|'s [=script fetcher/fetch duration=] to the [=duration from=] |fetchStart| to + |settings|'s [=environment settings object/current monotonic time=], in milliseconds. 1. Set |fetcher|'s [=script fetcher/script body=] to failure. 1. Set |fetcher|'s [=script fetcher/origins authorized for cross origin trusted signals=] to the result of [=parsing allowed trusted scoring signals origins=] given |response|'s [=response/ @@ -7911,6 +8145,8 @@ a [=script fetcher=] |fetcher|: 1. Let |bodyReader| be result of [=ReadableStream/getting a reader=] from |bodyStream|. 1. Let |successSteps| be a set of steps that take a [=byte sequence=] |responseBody|, and perform the following: + 1. Set |fetcher|'s [=script fetcher/fetch duration=] to the [=duration from=] |fetchStart| to + |settings|'s [=environment settings object/current monotonic time=], in milliseconds. 1. If [=validate fetching response mime and body=] with |response|, |responseBody| and "`text/javascript`" returns false, set |fetcher|'s [=script fetcher/script body=] to failure.