diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..04f41dc4 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# Code of Conduct + +All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..6e204604 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,24 @@ +# Cascading Style Sheets (CSS) Working Group + +Contributions to this repository are intended to become part of Recommendation-track documents governed by the +[W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy-20040205/) and +[Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate +in the relevant W3C Working Group or make a non-member patent licensing commitment. + +If you are not the sole contributor to a contribution (pull request), please identify all +contributors in the pull request comment. + +To add a contributor (other than yourself, that's automatic), mark them one per line as follows: + +``` ++@github_username +``` + +If you added a contributor by mistake, you can remove them in a comment with: + +``` +-@github_username +``` + +If you are making a pull request on behalf of someone else but you had no part in designing the +feature, you can remove yourself with the above syntax. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..0f7c218c --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,4 @@ +All documents in this Repository are licensed by contributors +under the +[W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). + diff --git a/README.markdown b/README.markdown index 3212b1fe..68254b6e 100755 --- a/README.markdown +++ b/README.markdown @@ -10,3 +10,13 @@ We also maintain the [public-houdini mailing list](http://lists.w3.org/Archives/ New specifications are generally first incubated in the WICG, in particular: - [Animation Worklet](https://github.com/WICG/animation-worklet) + +# Tests + +For normative changes, a corresponding +[web-platform-tests](https://github.com/web-platform-tests/wpt) PR is highly appreciated. Typically, +both PRs will be merged at the same time. Note that a test change that contradicts the spec should +not be merged before the corresponding spec change. If testing is not practical, please explain why +and if appropriate [file an issue](https://github.com/web-platform-tests/wpt/issues/new) to follow +up later. Add the `type:untestable` or `type:missing-coverage` label as appropriate. + diff --git a/box-tree-api/Overview.bs b/box-tree-api/Overview.bs index 9dec1467..2b71cd5b 100644 --- a/box-tree-api/Overview.bs +++ b/box-tree-api/Overview.bs @@ -6,11 +6,11 @@ ED: https://drafts.css-houdini.org/box-tree-api-1/ Shortname: box-tree-api Level: 1 Abstract: Layout as described by CSS produces boxes that control how content is displayed and positioned. This specification describes an API for accessing information about these boxes. -Editor: Tab Atkins, jackalmage@gmail.com -Editor: Peter Linss, peter.linss@hp.com -Editor: Ian Kilpatrick, ikilpatrick@chromium.org -Editor: Rossen Atanassov, rossen.atanassov@microsoft.com -Editor: Shane Stephens, shanestephens@google.com +Editor: Tab Atkins-Bittner, Google, http://xanthir.com/contact/, w3cid 42199 +Editor: Peter Linss, peter.linss@hp.com, w3cid 4200 +Editor: Ian Kilpatrick, ikilpatrick@chromium.org, w3cid 73001 +Editor: Rossen Atanassov, rossen.atanassov@microsoft.com, w3cid 49885 +Former Editor: Shane Stephens, shanestephens@google.com, w3cid 47691 @@ -33,26 +34,14 @@ Ignored Terms: PaintWorklet
-urlPrefix: https://heycam.github.io/webidl/; type: dfn;
-    text: InvalidModificationError
-    urlPrefix: #dfn-;
-        url: throw; text: thrown
-    urlPrefix: #idl-;
-        text: boolean
-        text: DOMException
-    url: es-type-mapping; text: converting
-urlPrefix: https://html.spec.whatwg.org/multipage/; type: dfn;
-    urlPrefix: scripting.html
-        text: reset the rendering context to its default state
-        text: output bitmap
-        text: set bitmap dimensions
-        url: concept-canvas-alpha; text: alpha
 urlPrefix: https://tc39.github.io/ecma262/#sec-; type: dfn;
     text: constructor
     text: Construct
@@ -61,7 +50,6 @@ urlPrefix: https://tc39.github.io/ecma262/#sec-; type: dfn;
     text: IsConstructor
     url: ecmascript-data-types-and-values; text: type
     url: get-o-p; text: Get
-    url: terms-and-definitions-function; text: function
     urlPrefix: native-error-types-used-in-this-standard-
         text: TypeError
 
@@ -78,63 +66,42 @@ response to size / computed style changes with an additional <> function. Note: In a future version of the spec, support could be added for defining the clip, global alpha, filter on a portion of a box (for example on the background layers). -Paint Invalidation {#paint-invalidation} -======================================== - -Each <> function for a box has an associated paint valid flag. It may be either -paint-valid or paint-invalid. It is initially set to paint-invalid. - -
-When the user agent wants to invalidate paint functions given |box|, the user agent -must run the following steps: - 1. For each <> function on the |box|, perform the following steps: - 1. Let |paintFunction| be the current <> function on the |box|. - - 2. Let |name| be the first argument of the <> function. - - 3. Let |documentPaintDefinitionMap| be the associated document's document paint - definitions map. - - 4. Let |documentDefinition| be the result of get - |documentPaintDefinitionMap|[|name|]. - - 5. Let |inputProperties| be |documentDefinition|'s input - properties list. - - 6. For each |property| in |inputProperties|, if the |property|'s computed value has - changed, set the paint valid flag on the |paintFunction| to paint-invalid. -
- -Performing draw a paint image results in the paint valid flag for a <> -function on a box to be set to paint-valid. - -Invalidate paint functions must be run when the user agent recalculates the computed -style for a box. - -Note: In a future version of the spec, support could be added for partial invalidation. The user - agent will be able to specify a region of the rendering context which needs to be re-painted by - the paint class. - Paint Worklet {#paint-worklet} ============================== The {{paintWorklet}} attribute allows access to the {{Worklet}} responsible for all the classes which are related to painting. -The {{paintWorklet}}'s worklet global scope type is {{PaintWorkletGlobalScope}}. +The {{paintWorklet}}'s [=worklet global scope type=] is {{PaintWorkletGlobalScope}}. + +The {{paintWorklet}}'s worklet destination type is "paintworklet".
-partial interface CSS {
+partial namespace CSS {
     [SameObject] readonly attribute Worklet paintWorklet;
 };
 
-The {{PaintWorkletGlobalScope}} is the global execution context of the {{paintWorklet}}. +A {{PaintWorkletGlobalScope}} is a global execution context of the {{paintWorklet}}. + +A {{PaintWorkletGlobalScope}} has a {{PaintWorkletGlobalScope/devicePixelRatio}} property which is +identical to the Window.{{Window/devicePixelRatio}} property.
 [Global=(Worklet,PaintWorklet),Exposed=PaintWorklet]
 interface PaintWorkletGlobalScope : WorkletGlobalScope {
-    void registerPaint(DOMString name, VoidFunction paintCtor);
+    undefined registerPaint(DOMString name, VoidFunction paintCtor);
+    readonly attribute unrestricted double devicePixelRatio;
+};
+
+ +The {{PaintRenderingContext2DSettings}} contains the settings for the rendering context associated +with the paint canvas. The {{PaintRenderingContext2DSettings}} provides a supported subset of canvas +rendering context 2D settings. In the future, it may be extended to support color management in +paint canvas. +
+dictionary PaintRenderingContext2DSettings {
+    boolean alpha = true;
 };
 
@@ -144,7 +111,7 @@ interface PaintWorkletGlobalScope : WorkletGlobalScope { class MyPaint { static get inputProperties() { return ['--foo']; } static get inputArguments() { return ['<color>']; } - static get alpha() { return true; } + static get contextOptions() { return {alpha: true}; } paint(ctx, size, styleMap) { // Paint code goes here. @@ -156,66 +123,70 @@ interface PaintWorkletGlobalScope : WorkletGlobalScope { Concepts {#concepts} ==================== -A paint definition is a struct which describes the information needed by the +A paint definition is a [=struct=] which describes the information needed by the {{PaintWorkletGlobalScope}} about the author defined <> (which can be referenced by the <> function). It consists of: - - class constructor which is the class constructor. + - class constructor which is the class [=constructor=]. - - paint function which is the paint function callback. + - paint function which is the paint [=Function=] + [=callback function=] type. - constructor valid flag. - - input properties which is a list of + - input properties which is a [=list=] of DOMStrings. - - A context alpha flag. + - A PaintRenderingContext2DSettings object. -A document paint definition is a struct which describes the information -needed by the document about the author defined <> function (which can be referenced +A document paint definition is a [=struct=] which describes the information +needed by the [=document=] about the author defined <> function (which can be referenced by the paint function). It consists of: - - A input properties which is a list of + - A input properties which is a [=list=] of DOMStrings. - - A input argument syntaxes which is a list of - parsed [[css-properties-values-api-1#supported-syntax-strings]]. + - A input argument syntaxes which is a [=list=] of + [=syntax definitions=]. - - A context alpha flag. + - A PaintRenderingContext2DSettings object. Registering Custom Paint {#registering-custom-paint} ==================================================== -The document has a map of document paint definitions. Initially +The [=document=] has a [=map=] of document paint definitions. Initially this map is empty; it is populated when {{registerPaint(name, paintCtor)}} is called. -The {{PaintWorkletGlobalScope}} has a map of paint definitions. Initially -this map is empty; it is populated when {{registerPaint(name, paintCtor)}} is called. +A {{PaintWorkletGlobalScope}} has a [=map=] of paint definitions. Initially this map +is empty; it is populated when {{registerPaint(name, paintCtor)}} is called. -The {{PaintWorkletGlobalScope}} has a map of paint class instances. Initially this -map is empty; it is populated when draw a paint image is invoked by the user agent. +A {{PaintWorkletGlobalScope}} has a [=map=] of paint class instances. Initially this +map is empty; it is populated when [=draw a paint image=] is invoked by the user agent. -Instances of paint classes in the paint class instances map may be disposed and removed from +Instances of paint classes in the [=paint class instances=] map may be disposed and removed from the map by the user agent at any time. This may be done when a <> function no longer is used, or the user agent needs to reclaim memory.
When the registerPaint(|name|, |paintCtor|) method is called, the user agent must run the following steps: - 1. If the |name| is an empty string, throw a TypeError and abort all these steps. + 1. If the |name| is an empty string, [=throw=] a [=TypeError=] and abort all these steps. - 2. Let |paintDefinitionMap| be {{PaintWorkletGlobalScope}}'s paint definitions map. + 2. Let |paintDefinitionMap| be {{PaintWorkletGlobalScope}}'s [=paint definitions=] map. - 3. If |paintDefinitionMap|[|name|] exists throw a - "InvalidModificationError" DOMException and abort all these steps. + 3. If |paintDefinitionMap|[|name|] [=map/exists=] [=throw=] a + "{{InvalidModificationError}}" {{DOMException}} and abort all these steps. 4. Let |inputProperties| be an empty sequence<DOMString>. - 5. Let |inputPropertiesIterable| be the result of Get(|paintCtor|, "inputProperties"). + 5. Let |inputPropertiesIterable| be the result of [=Get=](|paintCtor|, "inputProperties"). 6. If |inputPropertiesIterable| is not undefined, then set |inputProperties| to the result of - converting |inputPropertiesIterable| to a sequence<DOMString>. If an - exception is thrown, rethrow the exception and abort all these steps. + [=converting=] |inputPropertiesIterable| to a sequence<DOMString>. If an + exception is [=thrown=], rethrow the exception and abort all these steps. + + 7. Filter |inputProperties| so that it only contains [=supported CSS properties=] and + [=custom properties=]. Note: The list of CSS properties provided by the input properties getter can either be custom or native CSS properties. @@ -226,94 +197,94 @@ called, the user agent must run the following steps: also contains currently invalid properties for the user agent. For example margin-bikeshed-property. - 7. Let |inputArguments| be an empty sequence<DOMString>. + 8. Let |inputArguments| be an empty sequence<DOMString>. - 8. Let |inputArgumentsIterable| be the result of Get(|paintCtor|, "inputArguments"). + 9. Let |inputArgumentsIterable| be the result of [=Get=](|paintCtor|, "inputArguments"). - 9. If |inputArgumentsIterable| is not undefined, then set |inputArguments| to the result of - converting |inputArgumentsIterable| to a sequence<DOMString>. If an - execption is thrown, rethrow the execption and abort all these steps. + 10. If |inputArgumentsIterable| is not undefined, then set |inputArguments| to the result of + [=converting=] |inputArgumentsIterable| to a sequence<DOMString>. If an + exception is thrown, rethrow the exception and abort all these steps. - 10. Let |inputArgumentSyntaxes| be an empty list. + 11. Let |inputArgumentSyntaxes| be an [=list/empty=] [=list=]. - 11. For each |item| in |inputArguments| perform the following substeps: + 12. [=list/For each=] |item| in |inputArguments| perform the following substeps: - 1. Let |parsedSyntax| be the result of parsing |item| according to the rules in - [[css-properties-values-api-1#supported-syntax-strings]]. If it fails to parse - throw a TypeError and abort all these steps. + 1. Attempt to [=consume a syntax definition=] from |item|. + If failure was returned, [=throw=] a [=TypeError=] and abort all these steps. + Otherwise, let |parsedSyntax| be the returned [=syntax definition=]. - 2. Append |parsedSyntax| to |inputArgumentSyntaxes|. + 2. [=list/Append=] |parsedSyntax| to |inputArgumentSyntaxes|. - 12. Let |alphaValue| be the result of Get(|paintCtor|, "alpha"). + 13. Let |contextOptionsValue| be the result of [=Get=](|paintCtor|, "contextOptions"). - 13. Let |alpha| be true if |alphaValue| is undefined, otherwise let it be the - result of converting |alphaValue| to a boolean. If an exception is - thrown, rethrow the exception and abort all these steps. + 14. Let |paintRenderingContext2DSettings| be the result of [=converting=] + |contextOptionsValue| to a {{PaintRenderingContext2DSettings}}. + If an exception is [=thrown=], rethrow the exception and abort all these steps. - Note: Setting alpha is false allows user agents to anti-alias text - an addition to performing "visibility" optimizations, e.g. not painting an image behind - the paint image as the paint image is opaque. + Note: Setting paintRenderingContext2DSettings.alpha is false allows user agents + to anti-alias text in addition to performing "visibility" optimizations, e.g. not + painting an image behind the paint image as the paint image is opaque. - 14. If the result of IsConstructor(|paintCtor|) is false, throw a TypeError + 15. If the result of [=IsConstructor=](|paintCtor|) is false, [=throw=] a [=TypeError=] and abort all these steps. - 15. Let |prototype| be the result of Get(|paintCtor|, "prototype"). + 16. Let |prototype| be the result of [=Get=](|paintCtor|, "prototype"). - 16. If the result of Type(|prototype|) is not Object, throw a TypeError and + 17. If the result of [=Type=](|prototype|) is not Object, [=throw=] a [=TypeError=] and abort all these steps. - 17. Let |paint| be the result of Get(|prototype|, "paint"). + 18. Let |paintValue| be the result of [=Get=](|prototype|, "paint"). - 18. If the result of IsCallable(|paint|) is false, throw a TypeError and - abort all these steps. + 19. Let |paint| be the result of [=converting=] |paintValue| to the [=Function=] + [=callback function=] type. Rethrow any exceptions from the conversion. - 19. Let |definition| be a new paint definition with: + 20. Let |definition| be a new [=paint definition=] with: - - class constructor being |paintCtor|. + - [=paint definition/class constructor=] being |paintCtor|. - - paint function being |paint|. + - [=paint function=] being |paint|. - - constructor valid flag being true. + - [=paint definition/constructor valid flag=] being true. - - input properties being |inputProperties|. + - [=paint definition/input properties=] being |inputProperties|. - - context alpha flag being |alpha|. + - [=paint definition/PaintRenderingContext2DSettings object=] being |paintRenderingContext2DSettings|. - 20. Set |paintDefinitionMap|[|name|] to |definition|. + 21. [=map/Set=] |paintDefinitionMap|[|name|] to |definition|. - 21. Queue a task to run the following steps: + 22. [=Queue a task=] to run the following steps: - 1. Let |documentPaintDefinitionMap| be the associated document's document paint - definitions map. + 1. Let |documentPaintDefinitionMap| be the associated [=document's=] [=document paint + definitions=] [=map=]. - 2. Let |documentDefinition| be a new document paint definition with: + 2. Let |documentDefinition| be a new [=document paint definition=] with: - - input properties being |inputProperties|. + - [=document paint definition/input properties=] being |inputProperties|. - - input argument syntaxes being + - [=document paint definition/input argument syntaxes=] being |inputArgumentSyntaxes|. - - context alpha flag being |alpha|. + - [=document paint definition/PaintRenderingContext2DSettings object=] being |paintRenderingContext2DSettings|. - 3. If |documentPaintDefinitionMap|[|name|] exists, run the following steps: + 3. If |documentPaintDefinitionMap|[|name|] [=map/exists=], run the following steps: - 1. Let |existingDocumentDefinition| be the result of get + 1. Let |existingDocumentDefinition| be the result of [=map/get=] |documentPaintDefinitionMap|[|name|]. 2. If |existingDocumentDefinition| is "invalid", abort all these steps. 3. If |existingDocumentDefinition| and |documentDefinition| are not equivalent, (that is - input properties, input argument syntaxes, and context alpha flag are different), then: + definition">PaintRenderingContext2DSettings object are different), then: - Set |documentPaintDefinitionMap|[|name|] to "invalid". + [=map/Set=] |documentPaintDefinitionMap|[|name|] to "invalid". Log an error to the debugging console stating that the same class was registered with different inputProperties, inputArguments, or - alpha. + paintRenderingContext2DSettings. - 4. Otherwise, set |documentPaintDefinitionMap|[|name|] to + 4. Otherwise, [=map/set=] |documentPaintDefinitionMap|[|name|] to |documentDefinition|. Note: The list of input properties should only be looked up once, the class doesn't have the @@ -343,12 +314,12 @@ The <> function is an additional notation to be supported by the <
-For the 'cursor' property, the <> function should be treated as an invalid image and +For the 'cursor' property, the <> function should be treated as an [=invalid image=] and fallback to the next supported <>. -At computed value time the <> function does not need to match the grammar -registered by {{registerPaint()}}. Instead this will result in an invalid image when the -parsing occurs inside draw a paint image. +At [=computed value=] time the <> function does not need to match the grammar +registered by {{registerPaint()}}. Instead this will result in an [=invalid image=] when the +parsing occurs inside [=draw a paint image=]. The 2D rendering context {#2d-rendering-context} ================================================ @@ -357,36 +328,44 @@ The 2D rendering context {#2d-rendering-context} [Exposed=PaintWorklet] interface PaintRenderingContext2D { }; -PaintRenderingContext2D implements CanvasState; -PaintRenderingContext2D implements CanvasTransform; -PaintRenderingContext2D implements CanvasCompositing; -PaintRenderingContext2D implements CanvasImageSmoothing; -PaintRenderingContext2D implements CanvasFillStrokeStyles; -PaintRenderingContext2D implements CanvasShadowStyles; -PaintRenderingContext2D implements CanvasRect; -PaintRenderingContext2D implements CanvasDrawPath; -PaintRenderingContext2D implements CanvasDrawImage; -PaintRenderingContext2D implements CanvasPathDrawingStyles; -PaintRenderingContext2D implements CanvasPath; +PaintRenderingContext2D includes CanvasState; +PaintRenderingContext2D includes CanvasTransform; +PaintRenderingContext2D includes CanvasCompositing; +PaintRenderingContext2D includes CanvasImageSmoothing; +PaintRenderingContext2D includes CanvasFillStrokeStyles; +PaintRenderingContext2D includes CanvasShadowStyles; +PaintRenderingContext2D includes CanvasRect; +PaintRenderingContext2D includes CanvasDrawPath; +PaintRenderingContext2D includes CanvasDrawImage; +PaintRenderingContext2D includes CanvasPathDrawingStyles; +PaintRenderingContext2D includes CanvasPath; Note: The {{PaintRenderingContext2D}} implements a subset of the {{CanvasRenderingContext2D}} API. Specifically it doesn't implement the {{CanvasImageData}}, {{CanvasUserInterface}}, {{CanvasText}}, or {{CanvasTextDrawingStyles}} APIs. -A {{PaintRenderingContext2D}} object has a output bitmap. This is initialised when the -object is created. The size of the output bitmap is the size of the fragment it is -rendering. +A {{PaintRenderingContext2D}} object has a output bitmap. +This is initialised when the object is created. +The size of the [=PaintRenderingContext2D/output bitmap=] is the [=concrete object size=] +of the object it is rendering to. + +A {{PaintRenderingContext2D}} object also has an alpha flag, +which can be set to true or false. +Initially, when the context is created, +its alpha flag must be set to true. +When a {{PaintRenderingContext2D}} object has its alpha flag set to false, +then its alpha channel must be fixed to 1.0 (fully opaque) for all pixels, +and attempts to change the alpha component of any pixel must be silently ignored. -The size of the output bitmap does not necessarily represent the size of the actual bitmap +The size of the [=PaintRenderingContext2D/output bitmap=] does not necessarily represent the size of the actual bitmap that the user agent will use internally or during rendering. For example, if the visual viewport is zoomed the user agent may internally use bitmaps which correspond to the number of device pixels in the coordinate space, so that the resulting rendering is of high quality. Additionally the user agent may record the sequence of drawing operations which have been applied to -the output bitmap such that the user agent can subsequently draw onto a device bitmap at the -correct resolution. This also allows user agents to re-use the same output of the output -bitmap repeatably while the visual viewport is being zoomed for example. +the [=PaintRenderingContext2D/output bitmap=] such that the user agent can subsequently draw onto a device bitmap at the +correct resolution. This also allows user agents to re-use the same output of the [=PaintRenderingContext2D/output bitmap=] repeatably while the visual viewport is being zoomed for example. Whenever "currentColor" is used as a color in the {{PaintRenderingContext2D}} API, it is treated as opaque black. @@ -405,25 +384,42 @@ is treated as opaque black.
When the user agent is to create a PaintRenderingContext2D object for a given |width|, -|height|, and |alpha|, it must run the following steps: +|height|, and |paintRenderingContext2DSettings|, it must run the following steps: 1. Create a new {{PaintRenderingContext2D}}. - 2. Set bitmap dimensions for the context's output bitmap to |width| and |height|. - 3. Set the {{PaintRenderingContext2D}}'s alpha flag to |alpha|. + 2. [=Set bitmap dimensions=] for the context's [=PaintRenderingContext2D/output bitmap=] to the rounded values of |width| and |height|. + 3. Set the {{PaintRenderingContext2D}}'s [=PaintRenderingContext2D/alpha=] flag to |paintRenderingContext2DSettings|'s {{alpha}}. 4. Return the new {{PaintRenderingContext2D}}. -Note: The initial state of the rendering context is set inside the set bitmap dimensions - algorithm, as it invokes reset the rendering context to its default state and clears the - output bitmap. +Note: The initial state of the rendering context is set inside the [=set bitmap dimensions=] + algorithm, as it invokes [=reset the rendering context to its default state=] and clears the + [=PaintRenderingContext2D/output bitmap=].
+Drawing a CSSImageValue {#drawing-a-cssimagevalue} +-------------------------------------------------- + +The {{CanvasImageSource}} typedef is extended to also include the {{CSSImageValue}} type to be used +as an image source. + +For interfaces which use the {{CanvasDrawImage}} mixin: + - When a {{CanvasImageSource}} object represents an {{CSSImageValue}}, the result of invoking + the value's underlying image algorithm must be used as the source image for the purposes of + {{CanvasDrawImage/drawImage}}. + +Note: This should eventually be moved to the canvas section of the HTML specification. +See Issue 819. + Drawing an image {#drawing-an-image} ==================================== -If a <> function for a box is paint-invalid and the box is inside the -visual viewport, then user agent must draw a paint image for the current frame. +If a <> function image for a [=box=] is within the visual viewport, the user agent +must display an image output from an invocation of the [=draw a paint image=] algorithm. + +Note: The user agent doesn't have to run [=draw a paint image=] each frame for a <> + function within the visual viewport. It can cache results, (potentially using additional + invalidation steps) to display the correct image output. -Note: The user agent can optionally defer drawing images which are paint-invalid and outside - the visual viewport. +Note: The user agent can optionally defer drawing images which are outside the visual viewport.
If an author updates a style inside a requestAnimationFrame, e.g. @@ -433,22 +429,40 @@ Note: The user agent can optionally defer drawing images which are paint-inva }); And the element is inside the visual viewport, the user agent is required to - draw a paint image and display the result for the current frame. + [=draw a paint image=] and display the result for the current frame.
-The draw a paint image function is invoked by the user agent during the object size -negotiation algorithm which is responsible for rendering an <>. +The [=draw a paint image=] function is invoked by the user agent during the [=object size +negotiation=] algorithm which is responsible for rendering an <>, with +|snappedConcreteObjectSize| defined as follows. Let |concreteObjectSize| be the [=concrete object +size=] of the [=box=]. The |snappedConcreteObjectSize| is usually the same as the +|concreteObjectSize|. However, the user agent may adjust the size such that it paints to pixel +boundaries. If it does, the user agent should adjust the |snappedConcreteObjectSize| by the +proportional change from its original size such that the <> function can adjust the drawing +accordingly. -For the purposes of the object size negotiation algorithm, the paint image has no -intrinsic dimensions. +For the purposes of the [=object size negotiation=] algorithm, the paint image has no +[=intrinsic dimensions=]. -Note: In a future version of the spec, the author could have the ability to specify the intrinsic - dimensions of the paint image. This will probably be exposed as a callback allowing the - author to define static intrinsic dimensions or dynamically updating the intrinsic - dimensions based on computed style and size changes. +Note: In a future version of the spec, the author could have the ability to specify the [=intrinsic + dimensions=] of the paint image. This will probably be exposed as a callback allowing the + author to define static [=intrinsic dimensions=] or dynamically updating the [=intrinsic + dimensions=] based on computed style and size changes. The {{PaintSize}} object represents the size of the image that the author should draw. This is -the concrete object size given by the user agent. +the |snappedConcreteObjectSize| given by the user agent. + +Note: See [[css-images-3#object-sizing-examples]] for examples on how the [=concrete object + size=] is calculated. + +The [=draw a paint image=] function may be speculatively invoked by the user agent at any point, +with any |snappedConcreteObjectSize|. The resulting image is not displayed. + +Note: User agents may use any heuristic to speculate a possible future value for + |snappedConcreteObjectSize|, for example speculating that the size remains unchanged. + +Note: Although the image is not displayed, it may still be cached, and subsequent invocations of + <> may use the cached image.
 [Exposed=PaintWorklet]
@@ -461,42 +475,32 @@ interface PaintSize {
 
When the user agent wants to draw a paint image of a <> function for a |box| into its appropriate stacking level (as defined by the property the CSS property its associated -with), given its |concreteObjectSize| (concrete object size) it must run the -following steps: +with), given |snappedConcreteObjectSize| it must run the following steps: 1. Let |paintFunction| be the <> function on the |box| which the user agent wants to draw. - 2. If the paint valid flag for the |paintFunction| is paint-valid the user agent - may use the drawn image from the previous invocation. If so it may abort - all these steps and use the previously drawn image. - - Note: The user agent for implementation reasons may also continue with all these steps in - this case. It can do this every frame, or multiple times per frame. - - 3. Set the paint valid flag for the |paintFunction| to paint-valid. - - 4. Let |name| be the first argument of the |paintFunction|. + 2. Let |name| be the first argument of the |paintFunction|. - 5. Let |documentPaintDefinitionMap| be the associated document's document paint - definitions map. + 3. Let |documentPaintDefinitionMap| be the associated [=document's=] [=document paint + definitions=] map. - 6. If |documentPaintDefinitionMap|[|name|] does not exist, let the image output - be an invalid image and abort all these steps. + 4. If |documentPaintDefinitionMap|[|name|] does not [=map/exist=], let the image output + be an [=invalid image=] and abort all these steps. - 7. Let |documentDefinition| be the result of get + 5. Let |documentDefinition| be the result of [=map/get=] |documentPaintDefinitionMap|[|name|]. - 8. If |documentDefinition| is "invalid", let the image output be an invalid - image and abort all these steps. + 6. If |documentDefinition| is "invalid", let the image output be an [=invalid + image=] and abort all these steps. - 9. Let |inputArgumentSyntaxes| be |documentDefinition|'s input argument syntaxes. - 10. Let |inputArguments| be the list of all the |paintFunction| arguments after + 8. Let |inputArguments| be the [=list=] of all the |paintFunction| arguments after the "paint name" argument. - 11. If |inputArguments| do not match the registered grammar given by |inputArgumentSyntaxes|, - let the image output be an invalid image and abort all these steps. + 9. If |inputArguments| do not match the registered grammar given by |inputArgumentSyntaxes|, let + the image output be an [=invalid image=] and abort all these steps.
This step may fail in the following cases: @@ -525,87 +529,83 @@ following steps: </script>
- example-1 produces an invalid image as "red" does not + example-1 produces an [=invalid image=] as "red" does not match the registered grammar. - example-2 produces an invalid image as there are too many function + example-2 produces an [=invalid image=] as there are too many function arguments. - 12. Let |workletGlobalScope| be a {{PaintWorkletGlobalScope}} from the list of worklet's - WorkletGlobalScopes from the paint {{Worklet}}. + 10. Let |workletGlobalScope| be a {{PaintWorkletGlobalScope}} from the list of [=worklet's + WorkletGlobalScopes=] from the paint {{Worklet}}, following the rules defined in + [[#global-scope-selection]]. - The user agent must have, and select from at least two {{PaintWorkletGlobalScope}}s - in the worklet's WorkletGlobalScopes list, unless the user agent is under - memory constraints. - - Note: This is to ensure that authors do not rely on being able to store state on the global - object or non-regeneratable state on the class. - - The user agent may also create a WorkletGlobalScope at this time, given the + The user agent may also [=create a WorkletGlobalScope=] at this time, given the paint {{Worklet}}. - 13. Run invoke a paint callback given |name|, |inputArguments|, |concreteObjectSize|, - |workletGlobalScope| optionally in parallel. + 11. Run [=invoke a paint callback=] given |name|, |inputArguments|, |snappedConcreteObjectSize|, + |workletGlobalScope| optionally [=in parallel=]. - Note: If the user agent runs invoke a paint callback on a thread in parallel, + Note: If the user agent runs [=invoke a paint callback=] on a thread [=in parallel=], it should select a paint worklet global scope which can be used on that thread.
When the user agent wants to invoke a paint callback given |name|, |inputArguments|, -|concreteObjectSize|, and |workletGlobalScope|, it must run the following steps: +|snappedConcreteObjectSize|, and |workletGlobalScope|, it must run the following steps: - 1. Let |paintDefinitionMap| be |workletGlobalScope|'s paint definitions map. + 1. Let |paintDefinitionMap| be |workletGlobalScope|'s [=paint definitions=] map. - 2. If |paintDefinitionMap|[|name|] does not exist, run the following steps: + 2. If |paintDefinitionMap|[|name|] does not [=map/exist=], run the following steps: - 1. Queue a task to run the following steps: + 1. [=Queue a task=] to run the following steps: - 1. Let |documentPaintDefinitionMap| be the associated document's document - paint definitions map. + 1. Let |documentPaintDefinitionMap| be the associated [=document=]'s [=document + paint definitions=] map. - 2. Set |documentPaintDefinitionMap|[|name|] to "invalid". + 2. [=map/Set=] |documentPaintDefinitionMap|[|name|] to "invalid". 3. The user agent should log an error to the debugging console stating that a class wasn't registered in all {{PaintWorkletGlobalScope}}s. - 2. Let the image output be an invalid image and abort all these steps. + 2. Let the image output be an [=invalid image=] and abort all these steps. Note: This handles the case where there could be a paint worklet global scope which didn't receive the {{registerPaint(name, paintCtor)}} for |name| (however another global scope did). A paint callback which is invoked on the other global scope could succeed, but - wont succeed on a subsequent frame when draw a paint image is called. + wont succeed on a subsequent frame when [=draw a paint image=] is called. - 3. Let |definition| be the result of get |paintDefinitionMap|[|name|]. + 3. Let |definition| be the result of [=get=] |paintDefinitionMap|[|name|]. - 4. Let |paintClassInstanceMap| be |workletGlobalScope|'s paint class instances map. + 4. Let |paintClassInstanceMap| be |workletGlobalScope|'s [=paint class instances=] map. - 5. Let |paintInstance| be the result of get |paintClassInstanceMap|[|name]|. If + 5. Let |paintInstance| be the result of [=get=] |paintClassInstanceMap|[|name]|. If |paintInstance| is null, run the following steps: - 1. If the constructor valid flag on |definition| is false, let the image output be an - invalid image and abort all these steps. + 1. If the [=paint definition/constructor valid flag=] on |definition| is false, let the image output be an + [=invalid image=] and abort all these steps. - 2. Let |paintCtor| be the class constructor on |definition|. + 2. Let |paintCtor| be the [=paint definition/class constructor=] on |definition|. - 3. Let |paintInstance| be the result of Construct(|paintCtor|). + 3. Let |paintInstance| be the result of [=Construct=](|paintCtor|). - If construct throws an exception, set the |definition|'s constructor valid - flag to false, let the image output be an invalid image and abort all these + If [=construct=] throws an exception, + set the |definition|'s [=paint definition/constructor valid flag=] to false, + let the image output be an [=invalid image=] and abort all these steps. - 4. Set |paintClassInstanceMap|[|name|] to |paintInstance|. + 4. [=map/Set=] |paintClassInstanceMap|[|name|] to |paintInstance|. - 6. Let |inputProperties| be |definition|'s input properties. + 6. Let |inputProperties| be |definition|'s [=paint definition/input properties=]. 7. Let |styleMap| be a new {{StylePropertyMapReadOnly}} populated with only the - computed value's for properties listed in |inputProperties|. + [=computed value=]'s for properties listed in |inputProperties|. - 8. Let |renderingContext| be the result of create a PaintRenderingContext2D object given: - - "width" - The width given by |concreteObjectSize|. - - "height" - The height given by |concreteObjectSize|. - - "alpha" - The context alpha flag given by |definition|. + 8. Let |renderingContext| be the result of [=create a PaintRenderingContext2D object=] given: + - "width" - The width given by |snappedConcreteObjectSize|. + - "height" - The height given by |snappedConcreteObjectSize|. + - "paintRenderingContext2DSettings" - The + [=paint definition/PaintRenderingContext2DSettings object=] given by |definition|. Note: The |renderingContext| is not be re-used between invocations of paint. Implicitly this means that there is no stored data, or state on the |renderingContext| between @@ -618,7 +618,7 @@ When the user agent wants to invoke a paint callback given |name|, |i images. 9. Let |paintSize| be a new {{PaintSize}} initialized to the width and height defined by - |concreteObjectSize|. + |snappedConcreteObjectSize|. 10. At this stage the user agent may re-use an image from a previous invocation if |paintSize|, |styleMap|, |inputArguments| are equivalent to that previous invocation. If so let the image @@ -662,14 +662,14 @@ When the user agent wants to invoke a paint callback given |name|, |i
- 11. Let |paintFunctionCallback| be |definition|'s paint function. + 11. Let |paintFunctionCallback| be |definition|'s [=paint function=]. - 12. Invoke |paintFunctionCallback| with arguments «|renderingContext|, |paintSize|, - |styleMap|, |inputArguments|», and with |paintInstance| as the callback this value. + 12. [=Invoke=] |paintFunctionCallback| with arguments «|renderingContext|, |paintSize|, + |styleMap|, |inputArguments|», and with |paintInstance| as the [=callback this value=]. If |paintFunctionCallback| does not complete within an acceptable time (as determined by the user agent, i.e. it is a "long running script") the user agent may terminate the - script, let the image output be an invalid image, and abort all these steps. + script, let the image output be an [=invalid image=], and abort all these steps. Note: User agents could provide tooling within their debugging tools to show authors how expensive their paint classes are. User agents could also how an "unresponsive script" @@ -677,12 +677,29 @@ When the user agent wants to invoke a paint callback given |name|, |i 13. The image output is to be produced from the |renderingContext| given to the method. - If an exception is thrown the let the image output be an invalid image. + If an exception is [=thrown=] the let the image output be an [=invalid image=]. Note: The contents of the resulting image are not designed to be accessible. Authors can communicate any useful information through the standard accessibility APIs. +Global Scope Selection {#global-scope-selection} +------------------------------------------------ + +When the user agent needs to select a {{PaintWorkletGlobalScope}} from the paint [=worklet's +WorkletGlobalScopes=] [=list=] it must: + + - Select from at least two {{PaintWorkletGlobalScope}}s, unless the user agent is under + memory constraints. + + - Not re-use the same {{PaintWorkletGlobalScope}} more than 1000 times in a row. + + Note: The 1000 limit was picked as a high upper bound, this limit may improve (downwards) + over time. + +Note: These rules exist to ensure that authors do not rely on being able to store state on the + global object or non-regeneratable state on the class. See [[worklets-1#code-idempotency]]. + Examples {#examples} ==================== @@ -722,7 +739,7 @@ Animations API. name: '--circle-color', syntax: '<color>', initialValue: 'black', - inherit: false + inherits: false }); CSS.paintWorklet.addModule('circle.js'); </script> @@ -844,8 +861,8 @@ registerPaint('arc', class { ctx.strokeStyle = args[0].cssText; // Determine the center point. - const x = geom.width / 2; - const y = geom.height / 2; + const x = geom.width / 2; + const y = geom.height / 2; // Convert the start and end angles to radians. const startAngle = this.convertAngle(args[1]) - Math.PI / 2; @@ -926,3 +943,80 @@ registerPaint('heading-color', class { } }); + +Example 5: Drawing outside an element's area {#example-5} +--------------------------------------------------------- + +It is possible to draw outside an element's area by using the 'border-image' property. + +
+<style>
+#overdraw {
+    --border-width: 10;
+
+    border-style: solid;
+    border-width: calc(var(--border-width) * 1px);
+
+    border-image-source: paint(overdraw);
+    border-image-slice: 0 fill;
+    border-image-outset: calc(var(--border-width) * 1px);
+
+    width: 200px;
+    height: 200px;
+}
+</style>
+<div id="overdraw"></div>
+<script>
+    CSS.paintWorklet.addModule('overdraw.js');
+</script>
+
+ +
+// overdraw.js
+registerPaint('overdraw', class {
+    static get inputProperties() { return ['--border-width']; }
+    paint(ctx, geom, properties) {
+        const borderWidth = parseInt(properties.get('--border-width'));
+        ctx.shadowColor = 'rgba(0,0,0,0.25)';
+        ctx.shadowBlur = borderWidth;
+
+        ctx.fillStyle = 'rgba(255, 255, 255, 1)';
+        ctx.fillRect(borderWidth,
+                     borderWidth,
+                     geom.width - 2 * borderWidth,
+                     geom.height - 2 * borderWidth);
+    }
+});
+
+ +Security Considerations {#security-considerations} +================================================== + +There are no known security issues introduced by these features. + +Privacy Considerations {#privacy-considerations} +================================================ + +* The timing of paint callbacks can be used as a high-bandwidth channel for detecting "visited" state for links. + (details) + This is not a fundamentally new privacy leak, + as visited state leaks from many interactions, + but absent any further mitigations, + this is a particularly high-bandwidth channel of the information. + + No official mitigations are planned at this time, + as this privacy leak needs to be addressed more directly + to fix all such channels. + +Changes {#changes} +================== + +Changes since the 9 August 2018 CR publication: + +* Filtered the list of input properties to a paint worklet to be only known or custom properties. + +* Added alpha flag to {{PaintRenderingContext2D}} to control whether the rendering surface is forced opaque or allows transparency. + +* Fix definition for the size of the output bitmap: + + > The size of the output bitmap is the concrete object size of the object it is rendering to size of the fragment it is rendering. diff --git a/css-paint-api/circle/index.html b/css-paint-api/circle/index.html index 569c82f7..60dffdae 100644 --- a/css-paint-api/circle/index.html +++ b/css-paint-api/circle/index.html @@ -23,7 +23,7 @@ name: '--circle-color', syntax: '', initialValue: 'black', - inherit: false + inherits: false }); (CSS.paintWorklet.addModule || paintWorkle.import)('circle.js'); diff --git a/css-paint-api/issues-cr-2018.bs b/css-paint-api/issues-cr-2018.bs new file mode 100644 index 00000000..65ee503f --- /dev/null +++ b/css-paint-api/issues-cr-2018.bs @@ -0,0 +1,57 @@ +Draft: https://www.w3.org/TR/2018/CR-css-paint-api-1-20180809/ +Title: CSS Painting API Level 1 +---- +Issue 1. +Summary: Broken LInks +From: Chris Lilley +Comment: https://github.com/w3c/css-houdini-drafts/issues/787 +Response: https://github.com/w3c/css-houdini-drafts/issues/787#issuecomment-411123499 +Closed: Accepted +Resolved: Editorial +---- +Issue 2. +Summary: CSS Paint API leaks browsing history +From: Deian Stefan +Comment: https://github.com/w3c/css-houdini-drafts/issues/791 +Response: https://github.com/w3c/css-houdini-drafts/issues/791#issuecomment-546460085 +Changes: https://github.com/w3c/css-houdini-drafts/commit/3c72275054d9d541e6526e2988567ad4d209f257 +Closed: Accepted +Resolved: Editor discretion +Verified: https://github.com/w3c/css-houdini-drafts/issues/791#issuecomment-546466424 +---- +Issue 3. +Summary: Typo: use snappedConcreteObjectSize in paint callback +From: Chris Harrelson +Comment: https://github.com/w3c/css-houdini-drafts/issues/800 +Changes: https://github.com/w3c/css-houdini-drafts/commit/735ea42edf09f8d69de1eddbc7e7691528f56963 +Closed: Accepted +Resolved: Editorial +---- +Issue 4. +Summary: Disconnect between css-paint-api-1 and HTML specs on CanvasImageSource +From: Alan Jeffrey +Comment: https://github.com/w3c/css-houdini-drafts/issues/819 +Response: https://github.com/w3c/css-houdini-drafts/issues/819#issuecomment-424360647 +Open: Waiting for HTML spec edits +---- +Issue 5. +Summary: Improve passing of large-scale data to PaintWorklet +From: John Wiesz +Comment: https://github.com/w3c/css-houdini-drafts/issues/872 +Response: https://github.com/w3c/css-houdini-drafts/issues/872#issuecomment-499903766 +Open: Waiting on edits to add new features to Properties an Values API +---- +Issue 6. +Summary: Cycle possibe using inputProperties() +From: Stephen McGruer +Comment: https://github.com/w3c/css-houdini-drafts/issues/877 +Response: https://github.com/w3c/css-houdini-drafts/issues/877#issuecomment-499922873 +Open: Needs Edits +---- +Issue 7. +Summary: Two-way communication between main thread and worklet +From: Samad Aghaei +Comment: https://github.com/w3c/css-houdini-drafts/issues/881 +Response: https://github.com/w3c/css-houdini-drafts/issues/881#issuecomment-546456591 +Closed: OutOfScope +---- diff --git a/css-paint-api/issues-cr-2018.html b/css-paint-api/issues-cr-2018.html new file mode 100644 index 00000000..9c7a0ccb --- /dev/null +++ b/css-paint-api/issues-cr-2018.html @@ -0,0 +1,128 @@ + + +CSS Painting API Level 1 Disposition of Comments for 2018-08-09 CR + + +

CSS Painting API Level 1 Disposition of Comments for 2018-08-09 CR

+ +

Dated Draft: https://www.w3.org/TR/2018/CR-css-paint-api-1-20180809/ + +

Editor's Draft: http://drafts.csswg.org/css-paint-api-1/ + +

The following color coding convention is used for comments:

+ +
    +
  • Accepted or Rejected and positive response +
  • Rejected and no response +
  • Rejected and negative response +
  • Deferred +
  • Out-of-Scope or Invalid and not verified +
+ +

Open issues are marked like this

+ +

An issue can be closed as Accepted, OutOfScope, +Invalid, Rejected, or Retracted. +Verified indicates commentor's acceptance of the response.

+
+Issue 1. #
+Summary:  Broken LInks
+From:     Chris Lilley
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/787
+Response: https://github.com/w3c/css-houdini-drafts/issues/787#issuecomment-411123499
+Closed:   Accepted
+Resolved: Editorial
+
+Issue 2. #
+Summary:  CSS Paint API leaks browsing history
+From:     Deian Stefan
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/791
+Response: https://github.com/w3c/css-houdini-drafts/issues/791#issuecomment-546460085
+Changes:  https://github.com/w3c/css-houdini-drafts/commit/3c72275054d9d541e6526e2988567ad4d209f257
+Closed:   Accepted
+Resolved: Editor discretion
+Verified: https://github.com/w3c/css-houdini-drafts/issues/791#issuecomment-546466424
+
+Issue 3. #
+Summary:  Typo: use snappedConcreteObjectSize in paint callback
+From:     Chris Harrelson
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/800
+Changes:  https://github.com/w3c/css-houdini-drafts/commit/735ea42edf09f8d69de1eddbc7e7691528f56963
+Closed:   Accepted
+Resolved: Editorial
+
+Issue 4. #
+Summary:  Disconnect between css-paint-api-1 and HTML specs on CanvasImageSource
+From:     Alan Jeffrey
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/819
+Response: https://github.com/w3c/css-houdini-drafts/issues/819#issuecomment-424360647
+Open:     Waiting for HTML spec edits
+
+Issue 5. #
+Summary:  Improve passing of large-scale data to PaintWorklet
+From:     John Wiesz
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/872
+Response: https://github.com/w3c/css-houdini-drafts/issues/872#issuecomment-499903766
+Open:     Waiting on edits to add new features to Properties an Values API
+
+Issue 6. #
+Summary:  Cycle possibe using inputProperties()
+From:     Stephen McGruer
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/877
+Response: https://github.com/w3c/css-houdini-drafts/issues/877#issuecomment-499922873
+Open:     Needs Edits
+
+Issue 7. #
+Summary:  Two-way communication between main thread and worklet
+From:     Samad Aghaei
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/881
+Response: https://github.com/w3c/css-houdini-drafts/issues/881#issuecomment-546456591
+Closed:   OutOfScope
+ diff --git a/css-paint-api/issues-list-2018-04-10.html b/css-paint-api/issues-list-2018-04-10.html new file mode 100644 index 00000000..34669236 --- /dev/null +++ b/css-paint-api/issues-list-2018-04-10.html @@ -0,0 +1,108 @@ + + +CSS Paint API Level 1 Disposition of Comments for 2018-04-10 WD + + +

CSS Paint API Level 1 Disposition of Comments for 2018-04-10 WD

+ +

Dated Draft: https://www.w3.org/TR/2018/WD-css-paint-api-1-20180410/ + +

Editor's Draft: http://drafts.csswg.org/css-paint-api-1/ + +

The following color coding convention is used for comments:

+ +
    +
  • Accepted or Rejected and positive response +
  • Rejected and no response +
  • Rejected and negative response +
  • Deferred +
  • Out-of-Scope or Invalid and not verified +
+ +

Open issues are marked like this

+ +

An issue can be closed as Accepted, OutOfScope, +Invalid, Rejected, or Retracted. +Verified indicates commentor's acceptance of the response.

+
+Issue 1. #
+Summary:  Filter out unsupported properties from inputProperties.
+From:     Darren Shen
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/523
+Response: https://github.com/w3c/css-houdini-drafts/issues/523#issuecomment-351219067
+Changes:  https://github.com/w3c/css-houdini-drafts/commit/50fa9b8bedde46462113d756d6895701d3d743d0
+Closed:   Accepted
+Resolved: Editor discretion
+
+Issue 2. #
+Summary:  Allow inputArguments define optional arguments.
+From:     zheeeng
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/763
+Response: https://github.com/w3c/css-houdini-drafts/issues/763#issuecomment-401653404
+Closed:   Deferred
+
+Issue 3. #
+Summary:  Need to convert paint function to WebIDL Function type.
+From:     Shiino Yuki
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/743
+Response: https://github.com/w3c/css-houdini-drafts/issues/743#issuecomment-379738324
+Changes:  https://github.com/w3c/css-houdini-drafts/commit/f9f174dca09f5149c3df558d1c8e74517df19f5e
+Closed:   Accepted
+Resolved: https://lists.w3.org/Archives/Public/public-houdini/2018Apr/0002.html 
+
+Issue 4. #
+Summary:  Use WebIDL callback interface inside of registerPaint.
+From:     Shiino Yuki
+Comment:  https://github.com/w3c/css-houdini-drafts/issues/743
+Response: https://github.com/w3c/css-houdini-drafts/issues/743#issuecomment-379738324
+Closed:   Rejected
+Resolved: https://lists.w3.org/Archives/Public/public-houdini/2018Apr/0002.html 
+Verified: https://github.com/w3c/css-houdini-drafts/issues/743#issuecomment-379646250
+ diff --git a/css-paint-api/issues-list-2018-04-10.txt b/css-paint-api/issues-list-2018-04-10.txt new file mode 100644 index 00000000..41cef9ac --- /dev/null +++ b/css-paint-api/issues-list-2018-04-10.txt @@ -0,0 +1,38 @@ +Draft: https://www.w3.org/TR/2018/WD-css-paint-api-1-20180410/ +Title: CSS Paint API Level 1 + +---- +Issue 1. +Summary: Filter out unsupported properties from inputProperties. +From: Darren Shen +Comment: https://github.com/w3c/css-houdini-drafts/issues/523 +Response: https://github.com/w3c/css-houdini-drafts/issues/523#issuecomment-351219067 +Changes: https://github.com/w3c/css-houdini-drafts/commit/50fa9b8bedde46462113d756d6895701d3d743d0 +Closed: Accepted +Resolved: Editor discretion +---- +Issue 2. +Summary: Allow inputArguments define optional arguments. +From: zheeeng +Comment: https://github.com/w3c/css-houdini-drafts/issues/763 +Response: https://github.com/w3c/css-houdini-drafts/issues/763#issuecomment-401653404 +Closed: Deferred +---- +Issue 3. +Summary: Need to convert paint function to WebIDL Function type. +From: Shiino Yuki +Comment: https://github.com/w3c/css-houdini-drafts/issues/743 +Response: https://github.com/w3c/css-houdini-drafts/issues/743#issuecomment-379738324 +Changes: https://github.com/w3c/css-houdini-drafts/commit/f9f174dca09f5149c3df558d1c8e74517df19f5e +Closed: Accepted +Resolved: https://lists.w3.org/Archives/Public/public-houdini/2018Apr/0002.html +---- +Issue 4. +Summary: Use WebIDL callback interface inside of registerPaint. +From: Shiino Yuki +Comment: https://github.com/w3c/css-houdini-drafts/issues/743 +Response: https://github.com/w3c/css-houdini-drafts/issues/743#issuecomment-379738324 +Closed: Rejected +Resolved: https://lists.w3.org/Archives/Public/public-houdini/2018Apr/0002.html +Verified: https://github.com/w3c/css-houdini-drafts/issues/743#issuecomment-379646250 +---- diff --git a/css-parser-api/Overview.bs b/css-parser-api/Overview.bs index b0e54f52..82f9a00d 100644 --- a/css-parser-api/Overview.bs +++ b/css-parser-api/Overview.bs @@ -5,7 +5,7 @@ Level: 1 Status: UD Group: HOUDINI URL: https://drafts.css-houdini.org/css-parser-api/ -Editor: Tab Atkins-Bittner +Editor: Tab Atkins-Bittner, Google, http://xanthir.com/contact/, w3cid 42199 Abstract: An API exposing the CSS parser more directly, Abstract: for parsing arbitrary CSS-like languages into a mildly typed representation. diff --git a/css-properties-values-api/Overview.bs b/css-properties-values-api/Overview.bs index 0f5c968b..1caace06 100644 --- a/css-properties-values-api/Overview.bs +++ b/css-properties-values-api/Overview.bs @@ -3,16 +3,18 @@ Title: CSS Properties and Values API Level 1 Status: ED Group: houdini ED: https://drafts.css-houdini.org/css-properties-values-api-1/ +TR: https://www.w3.org/TR/css-properties-values-api-1/ +Previous Version: https://www.w3.org/TR/2017/WD-css-properties-values-api-1-20171109/ Previous Version: http://www.w3.org/TR/2016/WD-css-properties-values-api-1-20160607/ Shortname: css-properties-values-api Level: 1 Abstract: This CSS module defines an API for registering new CSS properties. Properties registered using this API are provided with a parse syntax that defines a type, inheritance behaviour, and an initial value. -Editor: Tab Atkins, jackalmage@gmail.com -Editor: Shane Stephens, shanestephens@google.com -Editor: Daniel Glazman, daniel.glazman@disruptive-innovations.com -Editor: Alan Stearns, stearns@adobe.com -Editor: Elliot Sprehn, esprehn@chromium.org -Editor: Greg Whitworth, gwhit@microsoft.com +Editor: Tab Atkins-Bittner, Google, http://xanthir.com/contact/, w3cid 42199 +Former Editor: Shane Stephens, shanestephens@google.com, w3cid 47691 +Editor: Daniel Glazman, daniel.glazman@disruptive-innovations.com, w3cid 13329 +Editor: Alan Stearns, stearns@adobe.com, w3cid 46659 +Former Editor: Elliot Sprehn, esprehn@chromium.org +Editor: Greg Whitworth, gwhit@microsoft.com, w3cid 69511 Ignored Terms: boolean, Animatable, Map, Context, isolated worker, SyntaxError, Ignored Terms: InvalidModificationError, NotFoundError, StylePropertyMapReadOnly, Ignored Terms: worklet global scope @@ -21,26 +23,29 @@ Ignored Terms: construct, name map of inputs Ignored Vars: arguments, methodPropertyKey, inputStyleMap, workletGlobalScope Ignored Terms: WorkletGlobalContext Repository: w3c/css-houdini-drafts - - -
-{
-	"css-paint-api": {
-		"title": "CSS Painting API"
-	},
-	"css-layout-api": {
-		"title": "CSS Layout API"
-	}
-}
+Markup Shorthands: css on, markdown on
 
Introduction {#intro} @@ -56,59 +61,563 @@ can only impact document layout or paint by being re-incorporated into the value of other properties via a var() reference. This specification extends [[css-variables]], allowing the registration of properties -that have a value type, an initial value, and a defined inheritance behaviour. +that have a value type, an initial value, and a defined inheritance behaviour, +via two methods: -This specification is complementary to [[css-paint-api]] and [[css-layout-api]], which +* A JS API, the {{registerProperty()}} method +* A CSS at-rule, the ''@property'' rule + +This specification is complementary to [[css-paint-api-1]] and [[css-layout-api-1]], which allow custom properties to directly impact paint and layout behaviours respectively. -Registering custom properties {#registering-custom-properties} -============================================================== + + + + +Registered Custom Properties {#behavior-of-custom-properties} +============================================================= + +A [=custom property=] can become a registered custom property, +making it act more like a UA-defined property: +giving it a syntax that's checked by the UA, +an initial value, +and a specific inheritance behavior. +This can be done by the ''@property'' rule, +or the {{registerProperty()}} JS function. + +A [=custom property=] is considered to be registered for a {{Document}} +if there is a valid ''@property'' rule +defined for its name +in one of the document's stylesheets, +or its name is [=map/contains|contained=] +in the document's {{[[registeredPropertySet]]}} slot +(that is, {{registerProperty()}} was called to register it). + +A [=registered custom property=] acts similarly to an unregistered [=custom property=], +except as defined below. + +Determining the Registration {#determining-registration} +-------------------------------------------------------- + +A [=registered custom property=] has a custom property registration +that contains all the data necessary to treat it like a real property. +It's a [=struct=] consisting of: + +* a property name (a [=custom property name string=]) +* a syntax (a [=syntax string=]) +* an inherit flag (a [=boolean=]) +* optionally, an initial value (a [=string=] which successfully [=CSS/parses=] according to the syntax) + +If the {{Document}}’s {{[[registeredPropertySet]]}} slot +[=set/contains=] a record with the [=custom property’s=] name, +the registration is that record. + +Otherwise, +if the {{Document}}’s active stylesheets contain at least one valid ''@property'' rule +representing a registration with the [=custom property’s=] name, +the last such one in document order is the registration. + +Otherwise there is no registration, +and the [=custom property=] is not a [=registered custom property=]. + +Parse-Time Behavior {#parsing-custom-properties} +------------------------------------------------ + +[=Registered custom properties=] parse exactly like unregistered [=custom properties=]; +almost anything is allowed. +The registered syntax of the property is not checked at parse time. + +Note: However, +the syntax is checked at computed-value time, +before substitution via ''var()''. +See [[#calculation-of-computed-values]]. + +
+ Why aren't custom properties syntax-checked? + + When parsing a page's CSS, + UAs commonly make a number of optimizations + to help with both speed and memory. + + One of those optimizations + is that they only store the properties that will actually have an effect; + they throw away invalid properties, + and if you write the same property multiple times in a single declaration block, + all but the last valid one will be thrown away. + (This is an important part of CSS's error-recovery + and forward-compatibility behavior.) + + This works fine if the syntax of a property never changes over the lifetime of a page. + If a custom property is registered, however, + it can change its syntax, + so that a property that was previously invalid + suddenly becomes valid. + + The only ways to handle this are to either store every declaration, + even those that were initially invalid + (increasing the memory cost of pages), + or to re-parse the entire page's CSS + with the new syntax rules + (increasing the processing cost of registering a custom property). + Neither of these are very desirable. + + Further, + UA-defined properties have their syntax determined + by the version of the UA the user is viewing the page with; + this is out of the page author's control, + which is the entire reason for CSS's error-recovery behavior + and the practice of writing multiple declarations for varying levels of support. + A custom property, on the other hand, + has its syntax controlled by the page author, + according to whatever stylesheet or script they've included in the page; + there's no unpredictability to be managed. + Throwing away syntax-violating custom properties + would thus only be, at best, a convenience for the page author, + not a necessity like for UA-defined properties. +
+ +[=Specified Value=]-Time Behavior {#specified-value} +---------------------------------------------------- + +Just like unregistered [=custom properties=], +all [=registered custom properties=], regardless of registered syntax, +accept the [=CSS-wide keywords=], +such as ''inherit'' or ''revert''. +Their behavior is defined in [[css-cascade-4#defaulting-keywords]]. + +[=Computed Value=]-Time Behavior {#calculation-of-computed-values} +------------------------------------------------------------------ + +The [=computed value=] of a [=registered custom property=] +is determined by the syntax of its [=registration=]. + +If the [=registration’s=] syntax is the [=universal syntax definition=], +the [=computed value=] is the same as for unregistered [=custom properties=] +(either the specified value with variables substituted, +or the [=guaranteed-invalid value=]). + +Otherwise, attempt to [=CSS/parse=] the property's value +according to its registered syntax. +If this fails, +the [=computed value=] is the [=guaranteed-invalid value=]. +If it succeeds, +the [=computed value=] depends on the specifics of the syntax: + +For "<length>", +"<length-percentage>", +"<angle>", +"<time>", +"<resolution>", +"<integer>", +"<number>", +and "<percentage>" values: + +* If the specified value is a [=dimension=] literal + (such as ''50em'' or ''.2s''), + the computed value is the same value, + but with the unit converted to the corresponding [=canonical unit=] + for the type of value. +* If the specified value is any other numeric literal + (such as ''5'' or ''20%''), + the computed value is as specified. + (In particular, percentages are never resolved against anything.) +* If the specified value is a function that evaluates to one of those types + (such as a [=math function=]), + the computed value is defined by that function. + +For "<color>" values, +the value is computed by [=resolving color values=]. + +For "<custom-ident>", ident, or "*" values, +the computed value is as specified. + +For "<url>" values, +the computed value is one of the following: + +* if the URL is a relative URL, + the computed value is the resolved absolute URL as described in [[!css3-values]]. +* otherwise, the computed value is as specified. + +
+ URL behavior examples +
+ Because URLs resolve against the base URL of the stylesheet they appear in, we can + end up with multiple relative URLs that resolve against different base URLs, even though + they appear in the same property. + + For example, suppose '--url-foo' and '--url-bar' are registered + custom properties with ''<url>'' syntax, and that we have a stylesheet at + /style/foo/foo.css: + +
+		div {
+			--url-foo: url("foo.png");
+		}
+		
+ + and another stylesheet at /style/bar/bar.css +
+		div {
+			--url-bar: url("bar.png");
+		}
+		
+ + and finally a document at /index.html: +
+		<link href="/style/foo/foo.css" rel="stylesheet" type="text/css">
+		<link href="/style/bar/bar.css" rel="stylesheet" type="text/css">
+		<div style="background-image: var(--url-foo), var(---url-bar);">
+		</div>
+		
+ + Here, the ''var(--url-foo)'' reference would produce a URL that resolves against + /style/foo, and the ''var(--url-bar)'' reference would produce a URL that resolves + against /style/bar. + + On the other hand, + if both '--url-foo' and '--url-bar' were unregistered, + they would substitute their literal values + (relative URLs) + into the /index.html stylesheet, + which would then resolve the URLs against /index.html instead. +
+
+ +For "<image>" values, +the computed value is the [=computed <image>=]. + +For "<transform-function>" and "<transform-list>" values, +the computed value is as specified but with all lengths resolved to their computed values. + +For values with [[#multipliers|multipliers]], +the computed value is a list of the computed values of the base type. + +For syntaxes specified with [[#combinator|the | combinator]], +the computed value is given by applying the computed-value rules +for the first clause that matches the value. + + +Animation Behavior {#animation-behavior-of-custom-properties} +------------------------------------------------------------- + +Note: As defined by [[css3-animations]] and [[css3-transitions]], it is possible to +specify animations and transitions that reference custom properties. + +When referenced by animations and transitions, +custom property values [=interpolate=] [=by computed value=], +in accordance with the type that they parsed as. + +Note: This implies that a list of values, +such as `+` or `#`, +will interpolate as a simple list, +matching up each component index-by-index, +and failing if the number of components doesn't match. + +As an exception to the above rule, +a value that parsed as a ``, +a ``, +or a `+` +instead interpolates as per the 'transform' property. + +Note: If, +for whatever reason, +a custom property is defined with a syntax of `#`, +this will thus first interpolate as a simple list, +and then each list item will interpolate as a 'transform' value. + +Note: Registering (or changing the registration) of a custom property +can change its computed value, +which can start or interrupt a CSS transition. + +Conditional Rules {#conditional-rules} +-------------------------------------- + +As stated in [[#parsing-custom-properties]], +both unregistered and [=registered=] [=custom properties=] +accept (almost) all possible values at parse-time. +[=Registered=] [=custom properties=] only apply their syntax at [=computed value=] time. + +So, all [=custom properties=], +regardless of whether they're [=registered=] or unregistered, +will test as "true" in an ''@supports'' rule, +so long as you don't violate the (very liberal) generic syntax for [=custom properties=]. + +
+ For example, + even if a custom property is registered + with syntax: "<color>";, + a rule like `@supports (--foo: 1em) {...}` + will still evaluate as true and apply those styles, + because the declaration does successfully parse as a valid property. +
+ + +Substitution via ''var()'' {#substitution} +------------------------------------------ + +Like unregistered custom properties, +the value of a registered custom property can be substituted into another value with the ''var()'' function. +However, registered custom properties substitute as their [[#calculation-of-computed-values|computed value]], +rather than the original token sequence used to produce that value. + +Any ''var()'' function that references a registered custom property +must be replaced with an equivalent token sequence, +which is equal to the token sequence that would have been produced +by [=serialize a CSS value|serializing=] the computed value, +and [[css-syntax-3#tokenization|tokenizing]] the resulting string. + +
+ Suppose that '--x' is registered with ''<length>'' syntax, + and that '--y'is an unregistered custom property. + +
+
+	div {
+		font-size: 10px;
+		--x: 8em;
+		--y: var(--x);
+	}
+	
+ + Because the computed value of '--x' (when serialized) is "80px", + the computed value of '--y' is + a <> with a value of "80" and unit "px". +
+ +### Fallbacks In ''var()'' References ### {#fallbacks-in-var-references} + +References to registered custom properties using the ''var()'' function may +provide a fallback. However, the fallback value must match the +syntax definition of the custom property being referenced, otherwise the +declaration is invalid at computed-value time. + +Note: This applies regardless of whether or not the fallback is being used. + + +### Dependency Cycles via Relative Units ### {#dependency-cycles} + +[=Registered custom properties=] follow the same rules for dependency cycle resolution +as unregistered [=custom properties=], +with the following additional constraints: + +For any registered custom property +with a <> or <> syntax component: + +* If the property contains any of the following units: + ''em'', ''ex'', ''cap'', ''ch'', ''ic'', ''lh''; + then add an edge between the property + and the ''font-size'' of the current element. +* If the property contains the ''lh'' unit, + add an edge between the property + and the ''line-height'' of the current element. +* If the property contains any of the following units: ''rem'', ''rlh''; + then add an edge between the property + and the 'font-size'' of the root element. +* If the property contains the ''rlh'' unit, + add an edge between the property + and the 'line-height'' of the root element. + +
+ For example, given this registration: + +
+	CSS.registerProperty({
+	  name: "--my-font-size",
+	  syntax: "<length>",
+	  initialValue: "0px",
+	  inherits: false
+	});
+	
+ + the following will produce a dependency cycle: + +
+	div {
+		--my-font-size: 10em;
+		font-size: var(--my-font-size);
+	}
+	
+ + and ''font-size'' will behave as if the value ''unset'' was specified. +
+ + + + + +The @property Rule {#at-property-rule} +================================================= + +The ''@property'' rule represents a [=custom property registration=] +directly in a stylesheet +without having to run any JS. +Valid ''@property'' rules result in a [=registered custom property=], +as if {{registerProperty()}} had been called with equivalent parameters. + +The syntax of ''@property'' is: + +
+	@property <> {
+		<>
+	}
+	
+ +A valid ''@property'' rule represents a [=custom property registration=], +with the property name being the serialization of the <> +in the rule's prelude. + +''@property'' rules require a 'syntax' and 'inherits' descriptor; +if either are missing, +the entire rule is invalid and must be ignored. +The 'initial-value' descriptor is optional +only if the syntax is the [=universal syntax definition=], +otherwise the descriptor is required; +if it's missing, the entire rule is invalid and must be ignored. + +Unknown descriptors are invalid and ignored, +but do not invalidate the ''@property'' rule. + +Note: As specified in [[#determining-registration]], +if multiple valid ''@property'' rules are defined for the same <>, +the last one in stylesheet order "wins". +A custom property registration from {{registerProperty()|CSS.registerProperty()}} +further wins over any ''@property'' rules +for the same <>. + +A ''@property'' is invalid if it occurs in a stylesheet inside of a [=shadow tree=], +and must be ignored. + +Issue(939): This will likely change in the future, +as the behavior of concept-defining at-rules in shadow trees +becomes more consistently defined. + +The 'syntax' Descriptor {#the-syntax-descriptor} +------------------------------------------------ + +
+	Name: syntax
+	Value: <>
+	For: @property
+	Initial: n/a (see prose)
+	
+ +Specifies the syntax of the [=custom property registration=] +represented by the ''@property'' rule, +controlling how the property's value is parsed at [=computed value=] time. + +The 'syntax' descriptor is required for the ''@property'' rule to be valid; +if it's missing, the ''@property'' rule is invalid. + +If the provided string is not a valid [=syntax string=] +(if it returns failure when [=consume a syntax definition=] is called on it), +the descriptor is invalid and must be ignored. + + +The 'inherits' Descriptor {#inherits-descriptor} +------------------------------------------------ + +
+	Name: inherits
+	Value: true | false
+	For: @property
+	Initial: n/a (see prose)
+	
+ +Specifies the inherit flag of the [=custom property registration=] +represented by the ''@property'' rule, +controlling whether or not the property inherits by default. + +The 'inherits' descriptor is required for the ''@property'' rule to be valid; +if it's missing, the ''@property'' rule is invalid. + + +The 'initial-value' Descriptor {#initial-value-descriptor} +---------------------------------------------------------- + +
+	Name: initial-value
+	Value: <>
+	For: @property
+	Initial: the [=guaranteed-invalid value=] (but see prose)
+	
+ +Specifies the initial value of the [=custom property registration=] +represented by the ''@property'' rule, +controlling the property’s [=initial value=]. + +If the value of the 'syntax' descriptor is the [=universal syntax definition=], +then the 'initial-value' descriptor is optional. +If omitted, the [=initial value=] of the property is the [=guaranteed-invalid value=]. + +Otherwise, +if the value of the 'syntax' descriptor is not the [=universal syntax definition=], +the following conditions must be met for the the ''@property'' rule to be valid: + + * The 'initial-value' descriptor must be present. + * The 'initial-value' descriptor's value must [=consume a syntax definition|parse successfully=] + according to the grammar specified by the [=syntax definition=]. + * The 'initial-value' must be [=computationally independent=]. + +If the above conditions are not met, the ''@property'' rule is invalid. + + + + +Registering Custom Properties in JS {#registering-custom-properties} +==================================================================== + +To register a custom property via JS, +the {{CSS}} object is extended with a {{registerProperty()}} method:
-dictionary PropertyDescriptor {
+dictionary PropertyDefinition {
 	required DOMString name;
 	         DOMString syntax       = "*";
-	         boolean   inherits     = false;
+	required boolean   inherits;
 	         DOMString initialValue;
 };
 
-partial interface CSS {
-	static void registerProperty(PropertyDescriptor descriptor);
-	static void unregisterProperty(DOMString name);
+partial namespace CSS {
+	undefined registerProperty(PropertyDefinition definition);
 };
 
Additional, the {{Document}} object gains a new \[[registeredPropertySet]] private slot, which is a set of records that describe registered custom properties. -The {{PropertyDescriptor}} dictionary {#the-propertydescriptor-dictionary} --------------------------------------------------------------------------- - -A PropertyDescriptor dictionary represents author-specified configuration -options for a custom property. {{PropertyDescriptor}} dictionaries contain the -following members: - -: name -:: The name of the custom property being defined. - -: syntax -:: A string representing how this custom property is parsed. - -: inherits -:: True if this custom property should inherit down the DOM tree; False otherwise. - -: initialValue -:: The initial value of this custom property. - -The {{registerProperty()}} and {{unregisterProperty()}} functions {#the-registerproperty-function} --------------------------------------------------------------------------------------------------- +The {{registerProperty()}} Function {#the-registerproperty-function} +-------------------------------------------------------------------- -The registerProperty(PropertyDescriptor descriptor) method +The registerProperty(PropertyDefinition definition) method registers a custom property according to the configuration options provided in -descriptor. +definition. When it is called, it executes the register a custom property algorithm, -passing the options in its descriptor argument +passing the options in its definition argument as arguments of the same names.
@@ -126,40 +635,21 @@ as arguments of the same names. associated Document's {{[[registeredPropertySet]]}} slot. - 2. Attempt to parse |name| - as a <>. - If this fails, + 2. If |name| is not a [=custom property name string=], throw a {{SyntaxError}} and exit this algorithm. - Otherwise, - let |parsed name| be the parsed value. - If |property set| - already contains an entry with |parsed name| as its property name + already contains an entry with |name| as its property name (compared codepoint-wise), throw an {{InvalidModificationError}} and exit this algorithm. - 3. If |syntax| is not present, - or is equal to "*" (U+002A ASTERISK), - let |parsed syntax| be undefined, - and skip to the next step of this algorithm. + 3. Attempt to [=consume a syntax definition=] from |syntax|. + If it returns failure, throw a {{SyntaxError}}. + Otherwise, let |syntax definition| be the returned syntax definition. - Otherwise, attempt to parse |syntax| - according to the rules in [[#supported-syntax-strings]]. - If it does not parse successfully, - throw a {{SyntaxError}}. - Otherwise, - let |parsed syntax| be the parsed syntax. - - Note: For example, a valid syntax string is something like "<length>", - or "<number>+"; - the allowed syntax is a subset of [[css-values-3#value-defs]]. - Future levels of this specification are expected to expand the complexity of allowed syntax strings, - allowing custom properties that more closely resemble the full breadth of what CSS properties allow. - - 4. If |parsed syntax| is undefined, + 4. If |syntax definition| is the universal syntax definition, and |initialValue| is not present, let |parsed initial value| be empty. This must be treated identically to the "default" initial value of custom properties, @@ -167,8 +657,8 @@ as arguments of the same names. Skip to the next step of this algorithm. Otherwise, - if |parsed syntax| is undefined, - parse |initialValue| as a <>. + if |syntax definition| is the universal syntax definition, + [=CSS/parse=] |initialValue| as a <>. If this fails, throw a {{SyntaxError}} and exit this algorithm. @@ -181,8 +671,8 @@ as arguments of the same names. and exit this algorithm. Otherwise, - parse {{PropertyDescriptor/initialValue}} - according to |parsed syntax|. + [=CSS/parse=] {{PropertyDefinition/initialValue}} + according to |syntax definition|. If this fails, throw a {{SyntaxError}} and exit this algorithm. @@ -192,16 +682,14 @@ as arguments of the same names. throw a {{SyntaxError}} and exit this algorithm. - 5. If |inherits| is present, - set |inherit flag| to its value. - Otherwise, set |inherit flag| to false. + 5. Set |inherit flag| to the value of |inherits|. - 6. Let |registered property| be a record - with a property name of |parsed name|, - a syntax of |parsed syntax|, + 6. Let |registered property| be a [=struct=] + with a property name of |name|, + a syntax of |syntax definition|, an initial value of |parsed initial value|, and an inherit flag of |inherit flag|. - Add |registered property| + [=set/Append=] |registered property| to |property set|.
@@ -230,42 +718,17 @@ the process via which specified values for that property are turned into compute is defined fully by the type selected, as described in [[#calculation-of-computed-values]]. -Properties can be unregistered using -unregisterProperty(DOMString name). -When it is called, -it executes the unregister a custom property algorithm, -with a name set to its sole argument. + Note: A way to unregister properties may be added in the future. -
- To unregister a custom property with the name |name|: - - 1. Let |property set| - be the value of the - current global object's - associated Document's - {{[[registeredPropertySet]]}} slot. - - 2. Attempt to parse |name| - as a <>. - If this fails, - throw a {{SyntaxError}} - and exit this algorithm. - - Otherwise, - let |parsed name| be the parsed value. - - 3. If |property set| - contains a record with a property name matching |parsed name| - (compared codepoint-wise), - remove the record from |property set|. - - Otherwise, - throw a {{NotFoundError}}. -
- -When the current global object's associated Document's {{[[registeredPropertySet]]}} changes, -previously syntactically invalid property values can become valid and vice versa. -This can change the set of declared values which requires the cascade to be recomputed. +Registering a custom property must not affect the [=cascade=] in any way. +Regardless of what syntax is specified for a registered property, +at parse time it is still parsed as normal for a [=custom property=], +accepting nearly anything. +If the [=specified value=] for a [=registered custom property=] +violates the registered syntax, +however, +the property becomes [=invalid at computed-value time=] +(and thus resets to the registered initial value).
By default, all custom property declarations that can be parsed as a sequence of tokens @@ -283,9 +746,11 @@ This can change the set of declared values which requires the cascade< The second '--my-color' declaration overrides the first at parse time (both are valid), and the ''var()'' reference in the 'color' property is found to be invalid at computed-value time (because ''url("not-a-color")'' is not a color). - At this stage of the CSS pipeline (computation time), the only available fallback is the initial value - of the property, which in the case of color is ''inherit''. Although there was a valid usable value - (green), this was removed during parsing because it was superseded by the URL. + At this stage of the CSS pipeline (computation time), + the only available fallback is the initial value of the property, + which in the case of color is ''inherit''. + Although there was a valid usable value (green), + this was removed during parsing because it was superseded by the URL. If we call: @@ -293,20 +758,104 @@ This can change the set of declared values which requires the cascade< CSS.registerProperty({ name: "--my-color", syntax: "<color>", - initialValue: "black" + initialValue: "black", + inherits: false }); - then the second '--my-color' declaration becomes syntactically invalid at parse time, - and is ignored. - The first '--my-color' is the only valid declaration left for the property, - so 'color' is set to the value ''green''. + the parsing doesn't significantly change, + regardless of whether the registration occurs before or after the stylesheet above. + The only difference is that it's the '--my-color' property that becomes [=invalid at computed-value time=] instead + and gets set to its initial value of ''black''; + then 'color' is validly set to ''black'', + rather than being [=invalid at computed-value time=] + and becoming ''inherit''.
-Supported syntax strings {#supported-syntax-strings} ----------------------------------------------------- +The {{PropertyDefinition}} Dictionary {#the-propertydefinition-dictionary} +-------------------------------------------------------------------------- -The following syntax strings are supported: +A PropertyDefinition dictionary represents author-specified configuration +options for a custom property. {{PropertyDefinition}} dictionaries contain the +following members: + +: name +:: The name of the custom property being defined. + +: syntax +:: A string representing how this custom property is parsed. + +: inherits +:: True if this custom property should inherit down the DOM tree; False otherwise. + +: initialValue +:: The initial value of this custom property. + + + + +Syntax Strings {#syntax-strings} +================================ + +A syntax string describes the value types accepted by a registered +custom property. Syntax strings consists of +[=syntax component names=], that are +optionally [[#multipliers|multiplied]] and [[#combinator|combined]]. + +A syntax string can be parsed into a syntax definition, which is either: + + 1. A list of syntax components, each of which accept the value types + specified in [[#supported-names]], or + 2. The universal syntax definition ('*'), which accepts any valid token + stream. + +Note: Regardless of the syntax specified, all custom properties accept +CSS-wide keywords, and process these values +appropriately. + +
+ For example, the following are all valid syntax strings. + + : "<length>" + :: accepts length values + : "<length> | <percentage>" + :: accepts lengths, percentages, percentage calc expressions, and length calc + expressions, but not calc expressions containing a combination of length + and percentage values. + : "<length-percentage>" + :: accepts all values that "<length> | <percentage>" would + accept, as well as calc expressions containing a combination of both length + and percentage values. + : "big | bigger | BIGGER" + :: accepts the ident big, or the ident bigger, or + the ident BIGGER. + : "<length>+" + :: accepts a space-separated list of length values. + : "*" + :: accepts any valid token stream +
+ +Note: The internal grammar of syntax strings is a subset of +[[css-values-3#value-defs|the CSS Value Definition Syntax]]. Future levels of this specification are expected +to expand the complexity of the allowed grammar, allowing custom properties +that more closely resemble the full breadth of what CSS properties allow. + +The remainder of this chapter describes the internal grammar of the syntax +strings. + +Supported Names {#supported-names} +---------------------------------- + +This section defines the supported syntax component names, and the +corresponding types accepted by the resulting syntax component. : "<length>" :: Any valid <> value @@ -331,144 +880,344 @@ The following syntax strings are supported: :: Any valid <