Skip to content

Commit 72e51de

Browse files
committed
[css-layout-api] Add contentSize callback algorithms.
1 parent 87a1397 commit 72e51de

File tree

2 files changed

+211
-4
lines changed

2 files changed

+211
-4
lines changed

css-layout-api/Overview.bs

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ urlPrefix: https://tc39.github.io/ecma262/#sec-; type: dfn;
6363
url: terms-and-definitions-function; text: function
6464
urlPrefix: native-error-types-used-in-this-standard-
6565
text: TypeError
66+
urlPrefix: https://drafts.csswg.org/css-display-3/#; type: dfn
67+
text: flow layout
68+
urlPrefix: https://drafts.csswg.org/css-sizing/#; type: dfn
69+
text: intrinsic sizes
6670
</pre>
6771

6872
Introduction {#intro}
@@ -733,6 +737,9 @@ name to child input properties map</dfn>. Initially these maps are empty and are
733737
Each <a>box</a> has an associated <dfn>layout valid flag</dfn>. It may be either
734738
<dfn>layout-valid</dfn> or <dfn>layout-invalid</dfn>. It is initially set to <a>layout-invalid</a>.
735739

740+
TODO comments. <dfn>content size valid flag</dfn>. <dfn>content-size-valid</dfn>.
741+
<dfn>content-size-invalid</dfn>.
742+
736743
Issue: The above flag is too restrictive on user agents, change.
737744

738745
When the computed style for a |box| changes, the user agent must run the following steps:
@@ -846,7 +853,8 @@ The {{LayoutWorkletGlobalScope}} has a <a>map</a> of <dfn>layout definitions</df
846853
map is empty; it is populated when {{registerLayout(name, layoutCtor)}} is called.
847854

848855
The {{LayoutWorkletGlobalScope}} has a <a>map</a> of <dfn>layout class instances</dfn>. Initially
849-
this map is empty; it is populated when {{registerLayout(name, layoutCtor)}} is called.
856+
this map is empty; it is populated when the user agent calls either <a>determine the content
857+
size</a> or <a>generate a fragment</a> for a <a>box</a>.
850858

851859
<div algorithm>
852860
When the <dfn method for=LayoutWorkletGlobalScope>registerLayout(|name|, |layoutCtor|)</dfn> method
@@ -1089,13 +1097,211 @@ dictionary ContentSizeResultOptions {
10891097
double maxContentSize;
10901098
double minContentSize;
10911099
};
1100+
1101+
interface ContentSize {
1102+
readonly attribute double minContentSize;
1103+
readonly attribute double maxContentSize;
1104+
};
10921105
</pre>
10931106

10941107
Issue: Specify how we do min/max content contributions.
10951108

10961109
Issue: Need to specify that the {{LayoutChild}} objects should remain the same between layouts so
10971110
the author can store information? Not sure.
10981111

1112+
<div algorithm="determine the content size">
1113+
When the user agent wants to <dfn>determine the content size</dfn> of a <a>layout API formatting
1114+
context</a> for a given |box|, |childBoxes| it <em>must</em> run the following steps:
1115+
1116+
1. Let |layoutFunction| be the <<layout()>> for the <a>computed value</a> of <<display-inside>>
1117+
for |box|.
1118+
1119+
2. If the <a>content size valid flag</a> for the |layoutFunction| is <a>content-size-valid</a>
1120+
the user agent <em>may</em> use the content size from the previous invocation. If so it
1121+
<em>may</em> abort all these steps and use the previous value for the content sizes.
1122+
1123+
3. Set the <a>content size valid flag</a> for the |layoutFunction| to <a>content-size-valid</a>.
1124+
1125+
4. Let |name| be the first argument of the |layoutFunction|.
1126+
1127+
5. Let |documentLayoutDefinitionMap| be the associated <a>document's</a> <a>document layout
1128+
definitions</a> map.
1129+
1130+
6. If |documentLayoutDefinitionMap|[|name|] does not <a for=map>exist</a>, let the |box|
1131+
fallback to the <a>flow layout</a> and abort all these steps.
1132+
1133+
7. Let |documentDefinition| be the result of <a for=map>get</a>
1134+
|documentLayoutDefinitionMap|[|name|].
1135+
1136+
8. If |documentDefinition| is <code>"invalid"</code>, let the |box| fallback to the <a>flow
1137+
layout</a> and abort all these steps.
1138+
1139+
9. Let |workletGlobalScope| be a {{LayoutWorkletGlobalScope}} from the list of <a>worklet's
1140+
WorkletGlobalScopes</a> fomr the layout {{Worklet}}.
1141+
1142+
The user agent <em>must</em> have, and select from at least two
1143+
{{LayoutWorkletGlobalScope}}s in the <a>worklet's WorkletGlobalScopes</a> <a>list</a>,
1144+
unless the user agent is under memory constraints.
1145+
1146+
Note: This is to ensure that authers do not rely on being able to store state on the global
1147+
object or non-regeneratable state on the class.
1148+
1149+
The user agent <em>may</em> also <a>create a WorkletGlobalScope</a> at this time, given the
1150+
layout {{Worklet}}.
1151+
1152+
10. Run <a>invoke a content size callback</a> given |name|, |box|, |childBoxes|, and
1153+
|workletGlobalScope| optionally <a>in parallel</a>.
1154+
1155+
Note: If the user agent runs <a>invoke a content size callback</a> on a thread <a>in
1156+
parallel</a>, it should select a layout worklet global scope which can be used on that
1157+
thread.
1158+
</div>
1159+
1160+
<div algorithm="invoke a content size callback">
1161+
When the user agent wants to <dfn>invoke a content size callback</dfn> given |name|, |box|,
1162+
|childBoxes|, and |workletGlobalScope|, it <em>must</em> run the following steps:
1163+
1164+
1. Let |definition| be the result of <a>get a layout definition</a> given |name|, and
1165+
|workletGlobalScope|.
1166+
1167+
If |definition| is <code>"null"</code>, (i.e. <a>get a layout definition</a> failed), let
1168+
the |box| fallback to the <a>flow layout</a> and abort all these steps.
1169+
1170+
2. Let |layoutInstance| be the result of <a>get a layout class instance</a> given |name|, |box|,
1171+
|definition|, |workletGlobalScope|.
1172+
1173+
If |layoutInstance| is <code>"null"</code>, (i.e. <a>get a layout class instance</a> failed),
1174+
let |box| fallback to the <a>flow layout</a> and abort all these steps.
1175+
1176+
3. Let |inputProperties| be |definition|'s <a for="layout definition">input properties</a>.
1177+
1178+
4. Let |childInputProperties| be |definition|'s <a for="layout definition">child input
1179+
properties</a>.
1180+
1181+
5. Let |styleMap| be a new {{StylePropertyMapReadOnly}} populated with <em>only</em> the
1182+
<a>computed value</a>'s for properties listed in |inputProperties| for |box|.
1183+
1184+
6. Let |children| be a new <a>list</a> populated with new {{LayoutChild}} objects which
1185+
represent |childBoxes|.
1186+
1187+
The {{LayoutChild/styleMap}} on each {{LayoutChild}} should be a new
1188+
{{StylePropertyMapReadOnly}} populated with <em>only</em> the <a>computed value</a>'s for
1189+
properties listed in |childInputProperties|.
1190+
1191+
7. Let |contentSizeGeneratorFunction| be |definition|'s <a>content size generator function</a>.
1192+
1193+
8. Let |contentSizeGenerator| be the result of <a>Invoke</a>(|contentSizeGeneratorFunction|,
1194+
|layoutInstance|, «|styleMap|, |children|»).
1195+
1196+
If an exception is <a>thrown</a> the let |box| fallback to the <a>flow layout</a> and abort
1197+
all these steps.
1198+
1199+
9. Let |nextResult| be the result of calling <a>Invoke</a>(<code>next</code>,
1200+
|contentSizeGenerator|).
1201+
1202+
If an exception is <a>thrown</a> the let |box| fallback to the <a>flow layout</a> and abort
1203+
all these steps.
1204+
1205+
10. Perform the following substeps until the result of <a>Get</a>(|nextResult|,
1206+
<code>"done"</code>) is <code>true</code>.
1207+
1208+
1. Let |childContentSizeRequests| be the result of <a>Get</a>(|nextResult|,
1209+
<code>"value"</code>).
1210+
1211+
2. Let |childContentSizes| be an <a for=list>empty</a> <a>list</a>.
1212+
1213+
3. <a for=list>For each</a> |childRequest| in |childContentSizeRequests| perform the
1214+
following substeps:
1215+
1216+
1. If |childRequest| is not a {{ContentSizeRequest}} then let |box| fallback to the
1217+
<a>flow layout</a> and abort all these steps.
1218+
1219+
2. Let |layoutChild| be result of looking up the internal slot
1220+
<code>\[[layoutChild]]</code> on |childRequest|.
1221+
1222+
3. Let |childContentSize| be a new {{ContentSize}} with:
1223+
1224+
- {{ContentSize/minContentSize}} being |layoutChild|'s <a>min-content size</a>.
1225+
1226+
- {{ContentSize/maxContentSize}} being |layoutChild|'s <a>max-content size</a>.
1227+
1228+
4. <a for=list>Append</a> |childContentSize| to |childContentSizes|.
1229+
1230+
The user agent may perform this loop out of order, and <a>in parallel</a>. The ordering
1231+
for |childContentSizes| and |childContentSizeRequests| <em>must</em> be consistent.
1232+
1233+
4. Let |nextResult| be the result of calling <a>Invoke</a>(<code>next</code>,
1234+
|contentSizeGenerator|, |childContentSizes|).
1235+
1236+
If an exception is <a>thrown</a> then let |box| fallback to the <a>flow layout</a> and
1237+
abort all these steps.
1238+
1239+
11. Let |contentSizeValue| be the result of calling <a>Get</a>(|nextResult|,
1240+
<code>"value"</code>).
1241+
1242+
12. Let |contentSize| be the result of <a>converting</a> |contentSizeValue| to a
1243+
{{ContentSizeResultOptions}}. If an exception is <a>thrown</a>, let |box| fallback to the
1244+
<a>flow layout</a> and abort all these steps.
1245+
1246+
13. Set the <a>intrinsic sizes</a> of |box|:
1247+
1248+
- Let |contentSize|'s {{ContentSizeResultOptions/minContentSize}} be the <a>min-content
1249+
size</a> of |box|.
1250+
1251+
- Let |contentSize|'s {{ContentSizeResultOptions/maxContentSize}} be the <a>max-content
1252+
size</a> of |box|.
1253+
</div>
1254+
1255+
<div algorithm="get a layout definition">
1256+
When the user agent wants to <dfn>get a layout definition</dfn> given |name|, and
1257+
|workletGlobalScope|, it <em>must</em> run the following steps:
1258+
1259+
1. Let |layoutDefinitionMap| be |workletGlobalScope|'s <a>layout definitions</a> map.
1260+
1261+
2. If |layoutDefinitionMap|[|name|] does not <a for=map>exist</a>, run the following steps:
1262+
1263+
1. <a>Queue a task</a> to run the following steps:
1264+
1265+
1. Let |documentLayoutDefinitionMap| be the associated <a>document</a>'s <a>document
1266+
layout definition</a> map.
1267+
1268+
2. <a for=map>Set</a> |documentLayoutDefinitionMap|[|name|] to <code>"invalid"</code>.
1269+
1270+
3. The user agent <em>should</em> log an error to the debugging console stating that a
1271+
class wasn't registered in all {{LayoutWorkletGlobalScope}}s.
1272+
1273+
2. Return <code>"null"</code>, and abort all these steps.
1274+
1275+
3. Return the result of <a>get</a> |layoutDefinitionMap|[|name|].
1276+
</div>
1277+
1278+
<div algorithm="get a layout class instance">
1279+
When the user agent wants to <dfn>get a layout class instance</dfn> given |name|, |box|,
1280+
|definition|, and |workletGlobalScope|, it <em>must</em> run the following steps:
1281+
1282+
1. Let |layoutClassInstanceMap| be |workletGlobalScope|'s <a>layout class instances</a> map.
1283+
1284+
2. Let |key| be a stable <a for=map>key</a> which is unique to |box| and |name|.
1285+
1286+
3. Let |layoutInstance| be the result of <a>get</a> |layoutClassInstanceMap|[|key|]. If
1287+
|layoutInstance| is null, run the following steps:
1288+
1289+
1. If the <a>constructor valid flag</a> on |definition| is false, let |box| fallback to the
1290+
<a>flow layout</a> and a abort all these steps.
1291+
1292+
2. Let |layoutCtor| be the <a>class constructor</a> on |definition|.
1293+
1294+
3. Let |layoutInstance| be the result of <a>Construct</a>(|layoutCtor|).
1295+
1296+
If <a>construct</a> throws an exception, set the |definition|'s <a>constructor valid
1297+
flag</a> to false, then return <code>"null"</code> and abort all these steps.
1298+
1299+
4. <a for=map>Set</a> |layoutClassInstanceMap|[|key|] to |layoutInstance|.
1300+
1301+
4. Return |layoutInstance|.
1302+
</div>
1303+
1304+
<div algorithm="generate a fragment">
10991305
When the user agent wants to <dfn>generate a fragment</dfn> of a <a>layout API formatting
11001306
context</a> for a given |box|, |constraintSpace|, |children| and an optional |breakToken| it
11011307
<em>must</em> run the following steps:
@@ -1229,3 +1435,4 @@ context</a> for a given |box|, |constraintSpace|, |children| and an optional |br
12291435
- The {{FragmentResultOptions/blockSize}} of the fragment.
12301436

12311437
15. Return |fragment|.
1438+
</div>

css-paint-api/Overview.bs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,8 @@ following steps:
539539
in the <a>worklet's WorkletGlobalScopes</a> <a>list</a>, unless the user agent is under
540540
memory constraints.
541541

542-
Note: This is to ensure that authors do not rely on being able to store state on the class
543-
or global object.
542+
Note: This is to ensure that authors do not rely on being able to store state on the global
543+
object or non-regeneratable state on the class.
544544

545545
The user agent <em>may</em> also <a>create a WorkletGlobalScope</a> at this time, given the
546546
paint {{Worklet}}.
@@ -591,7 +591,7 @@ When the user agent wants to <dfn>invoke a paint callback</dfn> given |name|, |i
591591

592592
3. Let |paintInstance| be the result of <a>Construct</a>(|paintCtor|).
593593

594-
If <a>Construct</a> throws an exception, set the |definition|'s <a>constructor valid
594+
If <a>construct</a> throws an exception, set the |definition|'s <a>constructor valid
595595
flag</a> to false, let the image output be an <a>invalid image</a> and abort all these
596596
steps.
597597

0 commit comments

Comments
 (0)