[Houdini] Minutes Lyon F2F 2018-10-25 Part I: Layout API

=================================================
   These are the official Houdini Task Force
     minutes. Unless you're correcting the
      minutes, please respond by starting
 a new thread with an appropriate subject line.
=================================================


Layout API
----------

  - Layout units when moving between microtask queue and task queue
      need to be defined.
  - It's not clear if layoutNextFragment should be renamed to
      something shorter (Issue #760), mostly because the group wasn't
      clear if this function and the callback should have the same
      name or different names.
  - RESOLVED: display:layout() works on fieldset, same as display:grid
              or display:flexbox do. (It applies to the inner box, and
              does not lay out the rendered legend.) (Issue #796)
  - RESOLVED: Publish a new version of the WD.

===== FULL MINUTES BELOW ======

Agenda: https://github.com/w3c/css-houdini-drafts/wiki/TPAC-F2F-October-2018

Present:
  Jia An, 360
  Rossen Atanassov, Microsoft
  Tab Atkins, Google
  L. David Baron, Mozilla
  Oriol Brufau, Igalia
  Tantek Çelik, Mozilla
  Emilio Cobos, Mozilla
  Dave Cramer, Hachette Livre
  Emil A Eklund, Google
  Elika Eteman, Invited Expert
  Simon Fraser, Apple
  Daniel Glazman, Privowny
  Arno Gourdol, Math on Web CG, observing
  Chris Harrelson, Google
  Jihye Hong, LGE
  Brian Kardell, JS Foundation
  Ian Kilpatrick, Google
  Vladimir Levin, Google
  Rune Lillesveen, Google
  Peter Linss, Invited Expert
  Cameron McCormack, Mozilla
  Manuel Rego, Igalia
  Florian Rivoal, Invited Expert
  Hiroshi Sakakibara, Beyond Perspective Solutions
  Dirk Schulze, Adobe
  Alan Stearns, Adobe
  Surma, Google
  Philip Walton, Google
  Greg Whitworth, Microsoft

Scribe: emilio

Layout API
==========

Review of Spec Changes
----------------------

  iank: I want to briefly go over the changes of the API
  iank: The biggest change is that the API is based on async functions
        instead of generators
  iank: and you need to await promises for getting intrinsic sizes /
        layout stuff
  iank: Basically s/yield/await s/*/async
  iank: From the performance point of view, you effectively process
        the task queue and run the JS microtask queue in a loop until
        you run out of tasks
  iank: You need to have these two stages because you can't run the
        microtask queue when there's other script running on the
        context
  iank: Questions?

  heycam: Does the separate task queue need HTML spec integration or
          something?
  iank: I don't believe it does because it's a separate task queue for
        the worklet
  iank: so it doesn't interact with any other stuff
  heycam: To bounce back from the microtask queue and this task queue
          you need some coordination right?
  iank: That's what this algorithm does yeah
  iank: The microtask queue is also local to the worklet scopes
  iank: We used to be worried about performance / complexity of
        microtasks and such, but ends up not being a problem
  iank: The next big change is that you used to return a dictionary,
        now you have a FragmentResult constructor that takes that
        dictionary, so you can check whether it throws and you can
        check the size of your own fragment and such
  iank: The only thing that is exposed on this FragmentResult object
        is the resulting inline size and block size

  smfr: Have you talked about the units for these sizes and such?
  iank: Yeah, but no conclusion yet... Everyone has different
        precision and such, but we haven't solved that problem yet
  Rossen: But do we have that problem?
  iank: You can come up with an example where the difference between
        engines may matter, but we haven't come up with such a problem
        in our examples
  eae: Plus that's how normal layout works usually
  Rossen: We should certainly have an issue on that
  iank: When you go into the layout engine we do the conversion to the
        layoutunits
  smfr: Is that round or ceil?
  iank: Round
  iank: One potential solution is to go to one fourth precision
  smfr: That's making assumptions about the current layout engines
        but...
  smfr: Is it spec'd that's round?
  eae: ??
  hober: ??
  smfr: I want to to spend some time on this issue
  Rossen: let's put it at the end of the queue for today
  <eae> On the other hand matching the native behavior is probably
        also important, for example if you have three items in a
        container where each gets 1/3rd of the size and one of them is
        native and the other two using custom layout.

  iank: The spec now also uses has a concept of a unique id for the
        current layout pass that you're doing, so that you can only
        use objects from the current layout pass
  iank: so that you can't reuse a fragment from the previous layout
        pass
  iank: We check that that matches the id of the current layout pass
        everywhere

  iank: The other change is that previously the Edges object that we
        pass into layout
  iank: Represented the border scroll and padding sizes of the css box
  iank: We realized that 99% of the time you want the sum of the
        border scrollbar padding
  iank: So we collapsed that object and you don't get the sizes
        individually and you just get that edge size
  iank: and it can give you the logical edges and convenient accessors
        for the sums
  iank: If the people need it they can do it resolving the padding
        property, but we could provide an API in the future

  heycam: Can I ask about scrollbars? What's the model regarding how
          scrollbars can appear or disappear?
  iank: It's up to the engine to determine the scrollable overflow,
        but you can call the layout() function multiple times with the
        new edges
  heycam: Is that algorithm defined?
  iank: No, since engines are all over the place
  iank: We try hard so that given the same inputs always give the same
        result, but I don't think it's feasible to spec this given
        where different engines are, it sucks
  iank: I believe that's about it for the major changes, there's a lot
        of other smaller changes

  iank: The one other change I thought it's significant is the
        LayoutWorkletGlobalScope choosing algorithm
  iank: You must choose between at least two different scopes from
        time to time
  iank: The other things that have this kind of ability are the
        StyleMap and layout children the engines pass in
  iank: They also need to be reset from time to time
  iank: Our engine will do something a bit more aggressive
  TabAtkins: In that must there should be an 'at least 1000 layout
             passes', need to be clear it could be less
  iank: We're going to do an origin trial realistically at the start
        of Q1, we've implemented most of the API but there's a few
        things we need to fix
  iank: Hopefully we get a bit of feedback

  Rossen: Which kind of layouts have you implemented?
  iank: We have this masonry layout I can show
  iank: This is still using the generator implementation
  iank: Body has display: layout(masonry)
  iank: There's two custom properties `--padding` and `--columns`
  iank: The order what you expect from an HTML layout, so it works
        with focus navigation and such
  iank: I've also added something like element queries based on the
        available size, so if you set --columns: auto and shrink the
        number of columns may change
  <iank> https://googlechromelabs.github.io/houdini-samples/layout-worklet/masonry/
  iank: The other demo doesn't work but it's basically a
        constraint-based layout where you can declare that A goes
        directly below B and you can stretch the elements depending on
        the constrains and such
  iank: We also have other unpublished bits
  surma: There's also /blocklike
  surma: So this is a very simplified version of block layout, which
         doesn't do margin collapsing
  surma: So that's something I'm very excited that developers can go
         ahead and try to understand how layout works
  surma: I also have a /random layout where you just do random position
  <surma> https://googlechromelabs.github.io/houdini-samples/layout-worklet/blocklike/
  <surma> https://googlechromelabs.github.io/houdini-samples/layout-worklet/random/
  iank: We've also prototyped flex-like layout and such
  iank: Once we ship the first pass of LayoutNG we plan to implement
        the fragmentation stuff
  iank: which should allow you to polyfill columns / shape-inside and
        such

  Rossen: So back to the topic, what's the current state of the spec?
          Any issue?
  iank: There are a few open issues in GH, I think I can close all of
        them
  iank: I believe all the other issues we've resolved on previously
        and can close
  iank: There's probably another issue we probably want to talk about
        which is renaming layoutNextFragment

layoutNextFragment
------------------
  github: https://github.com/w3c/css-houdini-drafts/issues/760

  iank: So we previously resolved to keep layoutNextFragment, but the
        more I use it it feels very long
  iank: So I want to rename to layout
  iank: So this LayoutChild.layoutNextFragment will become just
        layout, which also matches the callback name
  dbaron: I guess I think short names are good. I'm also a little
          hesitant about making people less aware of fragmentation.
          But I suppose that in many cases you don't fragment, so as
          long as when you do what happens is documented it's ok
  Rossen: Initially in the early stages of houdini we thought that
          this was mostly for middleware / framework authors and they
          need to understand it and that's why we chose to be
          consistent with layoutNextFragment
  Rossen: I'm leaning about keeping it, but I won't object to renaming
          it

  Rossen: So you haven't made any of the changes yet
  iank: Nope, one other option is to rename this to layoutFragment and
        rename the callback to layoutFragment, which is a bit clearer
        and shorter
  Rossen: and layoutFragment will be important when you start doing
          inline layout
  Rossen: So you wanted to revisit it based on feedback you got, you
          haven't made the changes yet, so the options is renaming
          layoutNextFragment to layout, or changing both the callback
          and the idl to layoutFragment
  Rossen: Thoughts?

  surma: I lean to have the same name for both
  Rossen: Oh sure, if we don't communicate that fragmentation can and
          will happen people won't care
  iank: Third proposal is layoutNextFragment for both of them
  heycam: I'm not actually super-sure about the symmetry since it
          seems like calling into layoutFragment to your child would
          call directly into the callback, but that's not what it's
          happening right?
  iank: Right, though we have that symmetry for intrinsic sizing
  cbiesinger: I think I really like layoutNextFragment, it's clearer
              that there might be more than one
  <fantasai> +1 to cbiesinger
  Rossen: I think first choice... do we want to insist for symmetry
          and keeping the same name? Since it's not really the same,
          so there needs not to be a symmetry between the two, which
          then leaves the question of just renaming layoutNextFragment
  <bkardell> if there is not symmetry here, for reasons - I think we
             need to be careful to follow that example in all the
             places

  smfr: layoutFragment is slightly ambiguous because I maybe interpret
        it as a name
  smfr: Where is the magic layout function used?
  iank: It's on registerLayout
  iank: There's a bug in WebIDL to handle classes instead of
        https://drafts.css-houdini.org/css-layout-api/#dom-layoutworkletglobalscope-registerlayout
  chrishtr: So if there are two fragments you may get called twice?
  iank: Yeah, if you return a break token you get called multiple times
  chrishtr: So layout() calls layoutNextFragment and that calls
            layout() potentially multiple times on the child right?
  chrishtr: So that example is not really exercising it right?
  iank: Yeah the line-by-line example exercises it
  iank: It's calling layoutNextFragment on the child multiple time
        until it's done
  chrishtr: I think layoutNextFragment makes more sense since it
            indicates an iterator pattern
  Rossen: That was the initial intent yeah
  iank: First question is should the callback have the same name
  surma: Layout doesn't return fragments right?
  iank: Yeah it does
  Rossen: layout() is called once for each fragment
  chrishtr: I'd keep the `Next`
  Rossen: So, keeping layoutNextFragment and renaming layout() to be
          either layoutFragment or layoutNextFragment?
  <dbaron> I'm leaning towards the idea that it's better for the names
           to be different so that it's clearer that one isn't calling
           the other, though I don't feel that strongly right now...

  Rossen: Can we live with layoutFragment? That'd make TabAtkins a
          little bit happier?
  TabAtkins: A third less happy
  <bkardell> I think layoutFragment/layoutNextFragment is less
             confusing actually
  surma: I think the symmetry helps it to be less confusing
  plinss: Having the same name I think it's more confusing
  plinss: Seems like it's calling the function directly instead of
          going through the engine
  <bkardell> +1 to what plinss said actually
  <gregwhitworth> I agree with bkardell and plinss (layoutFragment and
                  layoutNextFragment)
  TabAtkins: You can think a bit over it and ping us on a call or
             something
  Rossen: so no resolution?
  * emilio agrees with that too

  Rossen: What else is keeping the module from going forward?
  iank: The precision stuff

Should layout() apply to every element?
---------------------------------------
  https://github.com/w3c/css-houdini-drafts/issues/796

  TabAtkins: If display works on an element it display: layout()
             should work
  cbiesinger: There's a bunch of requests to make display work on
              fieldsets
  TabAtkins: At which point layout() should work
  emilio: fieldset display is weird because it only affects the
          display of the anonymous block inside it, at least on Gecko
  TabAtkins: So the "inner" display values work, just not the outer
             ones. (no block/inline, but flex/grid is fine)
  <TabAtkins> layout() is an "inner" display value.
  <TabAtkins> So it should work.

  emilio: Should you call layout() on the legend?
  TabAtkins: I'm happy to say legend is outside of your rendering, and
             that layout() is called for the contents of your inner box
  <rego> JFYI, "display: grid" on <fieldset> works in Firefox, Safari,
         Edge but not in Chromium
  <TabAtkins> (Because that's consistent with the behavior of
              display:grid on it; it only lays out the inner box,
              which doesn't include the <legend>)

  Rossen: So is the resolution that display layout() should work on
          any element that accepts a display value?
  emilio: What about replaced?
  TabAtkins: It only honors the outer display value, like setting
             display: grid on an image you just get a block
  emilio: What outer display does layout() have? block?
  TabAtkins: Yeah, thought we may want to add inline-layout() to
             handle that

  heycam: So display: layout() for an svg doesn't apply right?
  TabAtkins: hmm, so svg elements do honor display none... needs a bit
             better definition
  iank: So it's not a layout-api issue right?
  TabAtkins: No, css-display
  <TabAtkins> (or the theoretical svg-layout spec I've been
              threatening to write for a few years)

  Rossen: so... We have a resolution?
  TabAtkins: proposal: should work on fieldset
  Rossen: The title seemed a bit more general
  TabAtkins: I think except svg, fieldset is the only really special
             thing
  <TabAtkins> Proposed resolution: display:layout() works on fieldset,
              same as display:grid or display:flexbox do. (It applies
              to the inner box, and does not lay out the rendered
              legend.)

  RESOLVED: display:layout() works on fieldset, same as display:grid
            or display:flexbox do. (It applies to the inner box, and
            does not lay out the rendered legend.)

Publication
-----------

  Rossen: Other issues?
  iank: Nope

  RESOLVED: Publish a new version of the WD

Preloading
----------

  philipwalton: I'm wondering how much effort we're spending into
                throttled network stuff, or other way the developer
                could apply layout when loads are slow and such?
  iank: The promise return from the module load... You can use that
        when all the JS stuff loaded there is done
  iank: But it'd be interesting to have something like font loading
        works
  iank: I think we need to be able to load worklets declaratively
  iank: There has been talk in the past of a top level promise to the
        document
  iank: which it may be useful to allow people to wait for critical
        parts of the UI and such
  iank: but that's a separate discussion
  philipwalton: Is there an issue for that?
  iank: If you could file it'd be great
  TabAtkins: We definitely need to talk to the preload people to be
             able to load modules
  iank: And the TAG should probably be involved yeah

  Rossen: So that's all for layout, let's take a break and do typed OM
          when back

  <br dur=20min>

Received on Wednesday, 26 December 2018 22:52:10 UTC