[Houdini] Minutes Toronto F2F 2019-06-07 Part III: Layout API, Custom Functions Proposal, Publication Review

=================================================
   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
----------

  - RESOLVED: An unregistered or error'd layout() value causes
              blockification of the child elements, like the default
              value of childDisplay for a registered layout worker.
              (Issue #844: Unregistered layout function and
              blockification)
  - RESOLVED: Add a note, engines are allowed to do analysis to
              optimize the invalidation logic (Issue #898: Design to
              allow for more layout engine optimizations)
  - RESOLVED: Republish Layout API once IanK makes the edits from
              previous resolution.

Custom Functions Proposal
-------------------------

  - RESOLVED: Draft this proposal (
https://github.com/w3c/css-houdini-drafts/issues/857 )
              up as css-functions-api
  - RESOLVED: TabAtkins and AmeliaBR as editors

Publication Review
------------------

  - RESOLVED: Republish css-paint-api, properties and values,
              layout-api, typed-om
  - majidvp was actioned to publish the FPWD of animation worklet
      (previous resolved upon)

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

Agenda: https://github.com/w3c/css-houdini-drafts/wiki/Toronto-F2F-June-2019

Scribe: TabAtkins

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

Unregistered layout function and blockification
-----------------------------------------------
  github: https://github.com/w3c/css-houdini-drafts/issues/844

  iank: When we register a layout function, there is a childDisplay
        property which tells the rendering engine how to build a box
        tree
  iank: By default it will blockify everything, similar to flex and
        grid
  iank: Other mode doesn't
  iank: We haven't specified what happens if you put
        display:layout(...) but the ... isn't registered yet
  iank: I have a slightly pref for blockifying everything, as it's the
        default
  iank: Less change if there's an error in your layout function

  RESOLVED: An unregistered or error'd layout() value causes
            blockification of the child elements, like the default
            value of childDisplay for a registered layout worker.

Design to allow more layout engine optimizations
------------------------------------------------
  github: https://github.com/w3c/css-houdini-drafts/issues/898

  iank: Layout engines have a lot of optimizations for the inputs to
        layout
  iank: Gave one example in the issue that I think all UAs have today
  iank: Percent height descendant, if your height changes you have to
        lay out that subtree; if your height doesn't change you don't
        need to
  iank: While performing optimizations for layout, I realized it would
        be good for the layout api to get those optimizations too

  iank: We currently pass the layout() a bunch of information
  iank: It would be nice for the webdev to let us know which of these
        they actually use when generating the fragment
  iank: So if they only use the available sizes, and a percent size
        changes, we don't need to re-call them.
  iank: Today we can't optimize that

  iank: emilio this morning had the same idea I had; could we just
        figure out when a dev reads a particular property off the
        constraints?
  iank: Turns out not good enough. So we do need explicit dependencies
        expressed.
  AmeliaBR: They might check that property, but then switch and read a
            different property for actual use.
  iank: Right. You might read availableInlineSize, then switch to
        using percent size if it's small enough.
  dbaron: But you do still have a dependency then
  emilio: I commented about that, yeah.
  emilio: I thought the engine could be smart, but that's not enough.
          You need an allowlist, as your might branch off of something
          else to see which one you need.
  dbaron: If you have `if(A) { if(B) {...}}`, if you take the else,
          you don't have a dependency on B. You'll rerun layout when
          *A* changes, at which point you might be checking B, but
          before then you won't need to invalidate based on B
  <fremy> +1 to what dbaron just said
  myles: The story dbaron just told sounds scary...
  dbaron: I think it's less scary than making authors do it themselves
  dbaron: If authors do it themselves, they'll make the same mistake
          Ian did, and not mark dependencies (and thus get broken
          layouts)
  AmeliaBR: But that list of dependencies can change each time.
  emilio: If we have an allowlist I'd like to not expose the values
          that aren't allowed. But if we're just doing dependencies,
          I'm fine with all.
  proposed resolution: no change, engines are allowed to do analysis
      to optimize the invalidation logic

  RESOLVED: No change, engines are allowed to do analysis to optimize
            the invalidation logic

  dbaron: I think there should be a note in the spec about this
  iank: Definitely

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

  Rossen: Ian, can you repub this?
  iank: Yes.

  RESOLVED: Republish Layout API once IanK makes the edits from
            previous resolution.

Custom Functions Proposal
=========================
  Scribe: fantasai
  github: https://github.com/w3c/css-houdini-drafts/issues/857

  AmeliaBR: This is a proposal for a new module to have a way to have
            custom functions that you could use in CSS values
  AmeliaBR: Math functions, color functions, things that you put in a
            CSS value and it evaluates to an existing value type
  AmeliaBR: I sketched up a rough API in the proposal
  AmeliaBR: There's been good discussion over the past few months

  AmeliaBR: We separated things out into "stuff that can be easily
            isolated" vs. "stuff that is complicated"
  AmeliaBR: Looking at existing functions we have in CSS
  AmeliaBR: We have ones like the new math functions
  AmeliaBR: where they take an input value and output value
  AmeliaBR: End result is always the same for the parameter you gave
  AmeliaBR: sin(90deg) will always be sin(90deg), doesn't depend on
            the element
  AmeliaBR: On the other hand calc(percent + pixels) can't be
            evaluated until layout
  AmeliaBR: So that's simple idempotent functions that can do isolated
  AmeliaBR: vs ones that depend on DOM tree, inheritance, etc.

  AmeliaBR: Proposal at the time is to create Level 1 custom functions
            that only address the isolated idempotent case
  AmeliaBR: Always gives the same result for same parameters
  AmeliaBR: Except that we also allow putting in custom properties
  TabAtkins: Also allow *
  AmeliaBR: There will be arguments to the function, when you use the
            function you will know what they are

  AmeliaBR: One other issue that came up in the discussion
  AmeliaBR: what is the structure for declaring your custom function
  AmeliaBR: I based it on Paint API
  AmeliaBR: Valid suggestion that maybe that's overkill and doesn't
            need a custom class
  AmeliaBR: and maybe just need a registration object
  AmeliaBR: In this case one of the items of those configuration
            object would be an actual JS function
  AmeliaBR: That's a point of debate

  AmeliaBR: Question is do we go with class-based API or simple config
            option

  myles: Runs in a worklet?
  AmeliaBR: Yes, actual evaluation of function would be in a worklet
  AmeliaBR: Either way we need some isolated module so the function is
            defined in the global scope
  AmeliaBR: So doing custom property where you're registering all the
            data in the main thread doesn't work because the function
            you're including has to be in a separate module
  myles: Style resolution can be multithreaded
  myles: Is that compatible with this proposal?
  heycam: Our style resolution is multithreaded
  myles: Potentially one day ours might be too
  AmeliaBR: So long as you do dependency calculation for
            cross-references
  AmeliaBR: have to think of those dependencies
  AmeliaBR: but function itself is very isolatable
  TabAtkins: This is basically JS-computed var functions
  TabAtkins: ...
  emilio: Style resolution includes value computation
  iank: Architecturally this would be impossible
  myles: Paint has the same requirements
  iank: Paint has the ability to run on multiple threads

  heycam: I was going to ask about the worklet stuff as well
  heycam: Is it that we have to wait for worklet to synchronously
          finish its computation
  heycam: e.g. on getComputedStyle?
  heycam: Is that also what happens with layout?
  iank: If you call layout, we'll synchronously wait for it to finish
  TabAtkins: Have to run layout on getComputedStyle for width

  fantasai: If the value can't change per element, what's this useful
            for?
  fantasai: It cannot even depend on lengths: those can vary by element
            due to e.g. font-relative units.
  AmeliaBR: Custom color mod functions, custom math functions
  TabAtkins: Because we're waiting for computed value time, your ems
             are fine for example
  TabAtkins: we can resolve lengths beforehand
  fantasai: Oh you can resolve lengths; I had the impression from
            Amelia that you couldn't because length resolution varies
            per element and depends on e.g. font resolution
  AmeliaBR: Yeah, not percents since they depend on layout
  TabAtkins: The restrictions mean that it's not guaranteed for your
             function to be called for every element that matches it
             if they have the same input
  emilio: Then how does that work with multi-threading?
  TabAtkins: You're not required to not call the function multiple
             times
  AmeliaBR: You always get the same result
  emilio: But you can't guarantee that
  ...
  TabAtkins: Because you can invalidate a painter whenever, if you use
             random value it can flicker
  TabAtkins: same result here
  AmeliaBR: We can't force the Web author to write idempotent functions
  AmeliaBR: But can say browser is allowed to assume the function is
            idempotent
  emilio: If they write a non-idempotent, am I allowed to eat their
          laundry?
  [emilio's comment got lost in translation]
  dbaron: Invalidation thing is useful for debugging

  myles: So how do you implement random() with this?
  TabAtkins: You can't implement random() at this level
  AmeliaBR: If you look through issue discussion, brainstormed some
            ways that you could define just the right amount of
            randomness
  AmeliaBR: Do you want random per element -- same element get same
            result
  AmeliaBR: or random per element + property -- different result per
            property?
  AmeliaBR: That's part of the thing that's too complicated to deal
            with right now
  TabAtkins: Have plans for that, but not worry about that right now
  TabAtkins: Want to handle things like more math functions without
             going through WG

  myles: So hashing?
  TabAtkins: Yeah
  AmeliaBR: This is all about saying that browsers have a set of
            things they're looking at for when result will be
            invalidated, then it will be rerun
  AmeliaBR: They can also rerun whenever convenient
  AmeliaBR: That's the contract to authors

  heycam: This might already be partially answered by what happens in
          custom layout
  heycam: but what happens when worker throws exception or times out?
  TabAtkins: Invalid at computed value time
  heycam: Also the case that with custom layout, you just have to wait
          until browser decides it wants to recalculate that it will
          try again?
  TabAtkins: Whenever your inputs are changed, we invalidate
  TabAtkins: or whenever the browser feels like it
  myles: Wouldn't want it to be observable
  TabAtkins: If you had something that mapped out if (random < .5)
             throws exception
  TabAtkins: "please run me again I'll do better!"
  TabAtkins: Browser will run whenever it wants to, not because you
             failed
  myles: Presumably this would have the same thing as custom paint
         where it would throw away the world every so often?
  TabAtkins: Randomness is ill-defined

  majidvp: When I saw this proposal immediately what came to mind is
           our discussion yesterday about easing functions for
           animations
  majidvp: The current use case is focused on style resolution
  majidvp: but idea of stateless function with results cached
  majidvp: is similar to what we want for easing
  majidvp: I'm interested to see if we can make the design such that
           it can be used for partial currying
  majidvp: Example, one could have partial currying
  majidvp: you don't bind all the arguments at style resolution
  majidvp: Create function with some parameters bound at style
           resolution
  majidvp: and one variable, % progress, that gets fed in

  AmeliaBR: Way to think about it is, easing function in CSS is a
            function that returns as its value an f(x) type function
  AmeliaBR: Custom CSS function could return a function that was used
            as an easing function
  AmeliaBR: To do that, we'd need a TypedOM representation of an
            easing function
  AmeliaBR: Would be useful to create a custom easing function
  AmeliaBR: right now they're defined in a string
  AmeliaBR: but custom one, already talking about
  AmeliaBR: knock out lots of use cases for custom animation worklet
  AmeliaBR: wrap it up in a TypedOM object
  AmeliaBR: then your function in this proposal would return such an
            object
  AmeliaBR: That represents the easing function
  myles: Why can't you animate the input?
  AmeliaBR: I think there's some circularity there

  TabAtkins: This proposal is not meant to produce new value types
  TabAtkins: takes input to provide existing value type
  TabAtkins: If we need some new type of value, that would be a
             separate proposal
  TabAtkins: Once accepted could be something these functions can
             output

  AmeliaBR: Myles was saying ...
  AmeliaBR: converting your x progress to the change you want to have
  AmeliaBR: indirect way to get what you want
  majidvp: Basically bypassing web animations machinery
  ...
  TabAtkins: You can use a transition delay to set exactly where in
             the animation you want to be at that moment
  flackr: Thing deciding your animation position is being decided by
          another animation
  myles: We have that in animating custom properties
  myles: you animate custom property x from 0 to 1
  myles: you say left: custom-function(..x)
  flackr: will come up with the ?? proposal
  flackr: This will come up with our resolution on #869 where we can
          animate property --x from animation A and read that property
          in animation B to produce property --y.
  <AmeliaBR> `.el { width: custom-func(0px, 100px, var(--x)); --x: 0;
             transition: x 0.3s linear;} .el:hover { --x: 1}`
  myles: Do we need extra facilities?
  myles: Are we going to try to make custom functions return more
         functions?
  majidvp: No
  majidvp: I don't think we should do that, was just thinking
  majidvp: happy to limit right now
  AmeliaBR: Right now custom functions return TypedOM objects
  AmeliaBR: if we later have TypedOM objects for easing functions,
            it'll come along for the ride

  myles: In the GH issue it shows that the return type is a single type
  myles: but a CSS variable can expand to a sequence of things
  TabAtkins: No we don't need a return type if we build on variable
             machinery
  TabAtkins: You can output arbitrary, if you want to do that with
             TypedOM, you represent it as CSSUnparsedValue
  AmeliaBR: Not as useful to return an unparsedValue
  AmeliaBR: but I expect TypedOM to return lists and other complex
            types eventually
  emilio: Does this mean these need to be handled like variable
          references?
  TabAtkins: Yeah
  TabAtkins: you look sad :(
  emilio: No, it's fine
  emilio: but that means the input can be anything as well
  emilio: so same implications that ppl complain about
  AmeliaBR: Same resolutions as references in paint

  TabAtkins: I still should change env() to be not like variables, but
             at least for now will be more like variables. Can add
             more strongly typed later
  TabAtkins: Questions like "what happens if throws an error" get
             answered that way
  ...

  emilio: How do you resolve relative units?
  emilio: If input is unparsedvalue
  heycam: inputs are typed
  emilio: so input syntax is in the definition of the function
  TabAtkins: Yes. Unless you say *. But if you say <length> ems will
             resolve

  TabAtkins: I think I'm ready to write a spec for this if no one
             objections
  AmeliaBR: I will happily let you the work, but also happy to
            continue involved
  bkardell: co-editor involved?
  AmeliaBR: sure

  [spec naming discussion]
  myles: This has a bunch of JS stuff too
  Rossen: So proposed resolution is Tab and Amelia to co-edit CSS
          Custom Functions
  [more naming discussions]
  bkardell: I like keeping custom in there because it's not
            immediately clear to everyone that -- is our universal
            custom thing
  bkardell: so ties it in that way with custom properties
  <fantasai> css-functions
  <TabAtkins> css-functions-api
  <fantasai> function-api
  <dbaron> CSS Value Functions (as fullname)
  <TabAtkins> note that existing shortnames are "css-paint-api",
              "css-layout-api", "css-properties-values-api" and also
              css-variables
  <fremy> +1 to <css-funcs> CSS Value Functions
  <bkardell> +1 css functions api for the short name
  <Rossen> CSS Custom Functions
  <fantasai> bkardell, did you mean css-functions-api?
  <bkardell> yes
  <fantasai> AmeliaBR short & sweet, css-functions

  RESOLVED: Draft this proposal up as css-functions-api
  RESOLVED: TabAtkins and AmeliaBR as editors

  <bkardell> also resolved to include Custom in the title?
  Rossen: That's it for Houdini

Publication Review
==================

  Rossen: How are we doing in terms of Houdini specs?
  TabAtkins: Probably pretty bad
  Rossen: There have been major changes to a bunch of them, we should
          republish
  Rossen: Paint needs republishing, layout

  RESOLVED: Republish css-paint-api, properties and values,
            layout-api, typed-om

  majidvp: For animation worklet resolved to publishing FPWD last time
  jidvp: haven't done that yet
  ACTION majidvp FPWD animation worklet
  <trackbot> Created ACTION-880

Received on Thursday, 11 July 2019 23:13:44 UTC