diff --git a/css-mixins-1/Overview.bs b/css-mixins-1/Overview.bs index e998f0033c6..1bf9e2b3564 100644 --- a/css-mixins-1/Overview.bs +++ b/css-mixins-1/Overview.bs @@ -285,7 +285,7 @@ as well as other [=custom functions=] via <>s. The '@function/result' descriptor itself does not have a type, but its [=resolve function styles|resolved=] value is type-checked -during the [=substitute a dashed function|substitution=] of a <>. +during the [=replace a dashed function|substitution=] of a <>. Arguments & Local Variables {#args} ----------------------------------- @@ -385,7 +385,7 @@ with a <>. A <> is a [=functional notation=] whose function name starts with two dashes (U+002D HYPHEN-MINUS). -Its syntax is: +Its [=argument grammar=] is:
 	<dashed-function> = --*( <>#? )
@@ -396,7 +396,7 @@ A <> can only be used where ''var()'' is allowed.
 If a property contains one or more <>s,
 the entire property’s grammar must be assumed to be valid at parse time.
 At computed-value time,
-every <> must be [=substitute a dashed function|substituted=]
+every <> must be [=replace a dashed function|replaced=]
 before finally being checked against the property's grammar.
 
 Note: Within the body of a [=custom function=],
@@ -420,18 +420,18 @@ a [=calling context's=] root element
 is the real element at the root of the [=calling context=] stack.
 
 
- To substitute a dashed function in a value, - with |dashed function| being a <>: + To replace a dashed function |dashed function|, + with a list of |arguments|: 1. Let |function| be the result of dereferencing the |dashed function|'s name as a [=tree-scoped reference=]. - If no such name exists, return failure. - 2. [=substitute arbitrary substitution functions|Substitute=] - any [=arbitrary substitution functions=] - within |dashed function|'s arguments, - then parse it as ''<>#'' - and let |arguments| be the result - (a comma-separated list of CSS values). + If no such name exists, return the [=guaranteed-invalid value=]. + 2. For each |arg| in |arguments|, + [=substitute arbitrary subsitution functions=] in |arg|, + and replace |arg| with the result. + + Note: This may leave some (or all) arguments as the [=guaranteed-invalid value=], + triggering [=default values=] (if any). 3. If |dashed function| is being substituted into a property on an element, let |calling context| be a [=calling context=] with that element and that property @@ -442,17 +442,12 @@ is the real element at the root of the [=calling context=] stack. Let |calling context| be a [=calling context=] with that "hypothetical element" and that descriptor. - 5. [=Evaluate a custom function=], + 4. [=Evaluate a custom function=], using |function|, |arguments|, and |calling context|, - and replace the <> with the [=equivalent token sequence=] + and return the [=equivalent token sequence=] of the value resulting from the evaluation.
-If [=substitute a dashed function=] fails, -and the substitution is taking place on a property's value, -then the declaration containing the <> becomes -[=invalid at computed-value time=]. -
A [=comma-containing productions|comma-containing value=] may be passed as a single argument @@ -468,6 +463,66 @@ then the declaration containing the <> becomes
+
+ In the following, + --foo() is in a cycle with itself: + +
+	@function --foo(--x) {
+	  result: --foo(10);
+	}
+	
+ + Similarly, + --bar() is in a cycle with itself, + even though the local variable --x is never referenced + by '@function/result': + +
+	@function --bar() {
+	  --x: --bar();
+	  result: 1;
+	}
+	
+ + However, --baz() is not in a cycle with itself here, + since we never evaluate the result declaration within + the @media rule: + +
+	@function --baz(--x) {
+	  @media (unknown-feature) {
+	    result: --baz(42);
+	  }
+	  result: 1;
+	}
+
+	
+
+ +
+ The function --baz() is not in a cycle in the example below: + even though var(--x) and var(--y) appear in the function body, + they refer to a [=function parameter=] and [=local variable=], respectively. + The [=custom properties=] --x and --y + both reference --baz(), but that's fine: + those [=custom properties=] are not referenced within --baz(). + +
+	@function --baz(--x) {
+	  --y: 10px;
+	  result: calc(var(--x) + var(--y));
+	}
+
+	div {
+	  --x: --baz(1px);
+	  --y: --baz(2px);
+	  width: var(--x);  /* 11px */
+	  height: var(--y); /* 12px */
+	}
+	
+
+ Evaluating Custom Functions {#evaluating-custom-functions} ---------------------------------------------------------- @@ -486,18 +541,29 @@ with its [=function parameters=] overriding "inherited" custom properties of the and a list of CSS values |arguments|, returning a CSS value: - 1. If the number of items in |arguments| + 1. Let |substitution context| be a [=substitution context=] + containing &bs<<;"function", |custom function|&bs>>;. + + Note: Due to [=tree-scoped names|tree-scoping=], + the same function name may appear multiple times on the stack + while referring to different [=custom functions=]. + For this reason, the [=custom function=] itself is included + in the [=substitution context=], not just its name. + 2. [=guarded|Guard=] |substitution context| for the remainder of this algorithm. + If |substitution context| is marked as [=cyclic substitution context|cyclic=], + return the [=guaranteed-invalid value=]. + 3. If the number of items in |arguments| is greater than the number of [=function parameters=] in |custom function|, return the [=guaranteed-invalid value=]. - 2. Let |registrations| be an initially empty set of [=custom property registrations=]. - 3. For each [=function parameter=] of |custom function|, + 4. Let |registrations| be an initially empty set of [=custom property registrations=]. + 5. For each [=function parameter=] of |custom function|, create a [=custom property registration=] with the parameter's name, a syntax of the [=parameter type=], an inherit flag of "true", and no initial value. Add the registration to |registrations|. - 4. If |custom function| has a [=custom function/return type=], + 6. If |custom function| has a [=custom function/return type=], create a [=custom property registration=] with the name "return" (violating the usual rules for what a registration's name can be), @@ -505,33 +571,41 @@ with its [=function parameters=] overriding "inherited" custom properties of the an inherit flag of "false", and no initial value. Add the registration to |registrations|. - 5. Let |argument rule| be an initially empty [=style rule=]. - 6. For each [=function parameter=] of |custom function|: + 7. Let |argument rule| be an initially empty [=style rule=]. + 8. For each [=function parameter=] of |custom function|: 1. Let |arg value| be the value of the corresponding argument in |arguments|, or the [=guaranteed-invalid value=] if there is no corresponding argument. 2. Let |default value| be the parameter's [=default value=]. 3. Add a [=custom property=] to |argument rule| with a name of the parameter's name, and a value of ''first-valid(|arg value|, |default value|)''. - 7. [=Resolve function styles=] using |argument styles|, |registrations|, and |calling context|. + 9. [=Resolve function styles=] using |custom function|, |argument styles|, |registrations|, and |calling context|. Let |argument styles| be the result. - 8. Let |body rule| be the [=function body=] of |custom function|, + 10. Let |body rule| be the [=function body=] of |custom function|, as a [=style rule=]. - 9. For each [=custom property registration=] of |registrations|, + 11. For each [=custom property registration=] of |registrations|, set its initial value to the corresponding value in |argument styles|, set its syntax to the [=universal syntax definition=], and prepend a [=custom property=] to |body rule| with the property name and value in |argument styles|. - 10. [=Resolve function styles=] using |body rule|, |registrations|, and |calling context|. + 12. [=Resolve function styles=] using |custom function|, |body rule|, |registrations|, and |calling context|. Let |body styles| be the result. - 11. Return the value of the '@function/result' property in |body styles|. + 13. If |substitution context| is marked as a [=cyclic substitution context=], + return the [=guaranteed-invalid value=]. + + Note: Nested [=arbitrary substitution functions=] + may have marked |substitution context| as [=cyclic substitution context|cyclic=] + at some point after step 2, + for example when resolving '@function/result'. + 14. Return the value of the '@function/result' property in |body styles|.
To resolve function styles, - given a style rule |rule|, + given a [=custom function=] |custom function|, + a style rule |rule|, a set of [=custom property registrations=] |registrations|, and a [=calling context=] |calling context|, returning a set of [=computed value|computed=] styles: @@ -565,6 +639,17 @@ with its [=function parameters=] overriding "inherited" custom properties of the Note: ''result: inherit'', for example, will cause the <> to evaluate to the ''inherit'' keyword, similar to ''var(--unknown, inherit)''. + * For a given [=custom property=] |prop|, + during [=property replacement=] for that property, + the [=substitution context=] also includes |custom function|. + In other words, the [=substitution context=] is + &bs<<;"property", |prop|'s name, |custom function|&bs>>; + + Note: Due to dynamic scoping, + the same property name may appear multiple times on the stack + while referring to different [=custom properties=]. + For this reason, the [=custom function=] itself is included + in the [=substitution context=], not just its name. 3. Determine the [=computed value=] of all [=custom properties=] and the '@function/result' "property" on |el|, @@ -588,88 +673,6 @@ with its [=function parameters=] overriding "inherited" custom properties of the will be used from these styles.
- - - -Cycles {#cycles} ----------------- - -The ''@function/result'' descriptor and [=local variables=] -within a [=custom function=] -may reference other [=custom functions=] or [=custom properties=], -and may therefore create [[css-variables-1#cycles|cycles]]. - -For each element, add a node for every specified [=custom function=] -to the graph described in [[css-variables-1#cycles]]; -add a node for each [=local variable=] -defined within each of those functions; -then, for each [=custom function=] func, add edges as follows: - -* From func to any [=custom function=] - referenced by a <> within func's body. -* From func to any [=custom property=] or [=local variable=] - referenced by a ''var()'' within func's body. -* To func from any [=custom property=] or [=local variable=] - that references func - using a <>. - -A <> referencing a [=custom function=] -which is part of a cycle -makes the containing [=declaration=] [=invalid at computed-value time=]. - -Note: Cycles are disallowed even through branches that are not taken - during execution. - -
- In the following, - --foo() is in a cycle with itself, - even though the media query never evaluates to "true": - -
-	@function --foo(--x) {
-	  @media (unknown-feature) {
-	    result: --foo(42);
-	  }
-	  result: 1;
-	}
-	
- - Similarly, - --bar() is in a cycle with itself, - even though the local variable --x is never referenced: - -
-	@function --bar() {
-	  --x: --bar();
-	  result: 1;
-	}
-	
-
- -
- The function --baz() is not in a cycle in the example below: - even though var(--x) and var(--y) appear in the function body, - they refer to a [=function parameter=] and [=local variable=], respectively. - The [=custom properties=] --x and --y - both reference --baz(), but that's fine: - those [=custom properties=] are not referenced within --baz(). - -
-	@function --baz(--x) {
-	  --y: 10px;
-	  result: calc(var(--x) + var(--y));
-	}
-
-	div {
-	  --x: --baz(1px);
-	  --y: --baz(2px);
-	  width: var(--x);  /* 11px */
-	  height: var(--y); /* 12px */
-	}
-	
-
- -