Skip to content

CalcDictionary members probably shouldn't be nullable and have default values #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
heycam opened this issue Jan 30, 2016 · 10 comments
Closed

Comments

@heycam
Copy link
Contributor

heycam commented Jan 30, 2016

I'm not sure why the CalcDictionary members are all defined to be nullable and have null default values. As there's no definition of the LengthValue.fromDictionary method it's hard to tell. :-) But probably you just want:

dictionary CalcDictionary {
  double px;
  double percent;
  ...
};

and then in the definition of the fromDictionary method (and the CalcLength constructor) you can check whether a given dictionary member is present or not.

@shans
Copy link
Contributor

shans commented Mar 11, 2016

We need to know which units had a defined value (even if 0) when doing things like addition or interpolation. Just confirming - you only meant the above for CalcDictionary, not for CalcLength, right?

@heycam
Copy link
Contributor Author

heycam commented Mar 14, 2016

We need to know which units had a defined value (even if 0) when doing things like addition or interpolation.

Checking for the dictionary member being present or not lets you do that.

Just confirming - you only meant the above for CalcDictionary, not for CalcLength, right?

I did, but you could do it for CalcLength too. I'm not sure whether it's more idiomatic for objects being returned to script to use property presence to represent optionality, or to have all the properties on the object and use null.

@tabatkins
Copy link
Member

We need to know which units had a defined value (even if 0) when doing things like addition or interpolation.

Checking for the dictionary member being present or not lets you do that.

Shane said "when doing things like addition or interpolation". That's after construction.

You are correct that we don't need nullable for CalcDictionary, because we can just check for whether it's specified or not. That is still makes some patterns slightly awkward, but it's not killer. The same argument applies to optional function args, but ES purposely chose to allow specified undefined to mean the same as omitting, because otherwise certain patterns (like just wrapping another function) become much more awkward - you have to branch and make multiple distinct calls to avoid passing "unspecified" arguments to the wrapped function (or construct an arglist manually and use .apply). Constructing an object is a little different, because you can do it piecemeal - use a series of if blocks to control whether you set a property in the object, before passing it in - but without nulls it's still harder to use the object literal syntax in some cases.

But CalcLength needs nullable, no matter what. We operate under two competing constraints for serialization:

  1. Only serialize components that were actually specified, so you don't have a long list of calc(0px + 0em + 0vw + ...) (that changes as we add new units!).
  2. Don't drop specified components with a zero value, because it makes results harder to work with, particular in the middle of an animation. Halfway between calc(10px + 1em) and calc(10px - 1em) the em component is zero, but having to manually account for the possibility that the cl.em component will return null halfway through is a huge footgun.

#1 requires that we either allow null to indicate "not specified", or set all unspecified things to 0 and then omit 0s. #2 requires that we not omit 0s that were specified. So we have to allow nulls.

@upsuper
Copy link
Member

upsuper commented Mar 15, 2016

But making its nullable could be confusing. What's the meaning of null vs. unspecified in CalcLength, then? It is clear that we cannot make all of the items required.

In addition, making functions output a long object with lots of null fields for unspecified items doesn't sound sensible. Imagine that, you provide calc(10px + 1em), but some function returns:

{ px: 10, percent: null, em: 1, ex: null, ch: null, rem: null,
  vw: null, vh: null, vmin: null, vmax: null, cm: null, mm: null,
  q: null, in: null, pc: null, pt: null }

(Even longer in the future.)

Could we probably tolerate null/undefined values for input (that says, treat them as unspecified, or remove fields with those values before further handling), but make them non-nullable?

@tabatkins
Copy link
Member

What's the meaning of null vs. unspecified in CalcLength, then?

You're mixing concepts. That's a recipe for confusion!

In the current spec for CalcDictionary, there's no difference between a key being unspecified, and it being specified with null. Either way results in the appropriate CalcLength attribute being set to null.

In CalcLength, there's no such thing as "unspecified". It's got a bunch of attributes, which are always present. Some of them are nullable. These get set to null by the CalcDictionary-based constructor as described above, or by the .parse() method, where every unit that's not explicitly present in the calc(...) string is set to null.

@tabatkins
Copy link
Member

In addition, making functions output a long object with lots of null fields for unspecified items doesn't sound sensible.

I'm not making any function output that. I think you read my previous response wrong.

@heycam
Copy link
Contributor Author

heycam commented Mar 15, 2016

Constructing an object is a little different, because you can do it piecemeal - use a series of if blocks to control whether you set a property in the object, before passing it in - but without nulls it's still harder to use the object literal syntax in some cases.

Note that explicit undefined will be treated the same as a missing dictionary member. So you could still have:

dictionary CalcDictionary {
  double px;
  double percent;
  ...
};

and write new CalcLength({ px: 1, percent: something ? 50 : undefined }).

@heycam
Copy link
Contributor Author

heycam commented Mar 15, 2016

In CalcLength, there's no such thing as "unspecified".

For some reason I thought CalcLength was a dictionary. Ignore my suggestion about making members unspecified there (which doesn't make sense for IDL attributes).

@tabatkins
Copy link
Member

Ah, I wasn't aware that explicit undefined had the same "pretend it wasn't specified" behavior in dictionaries as it did in argument lists. Cool.

In that case, great, let's make CalcDictionary members non-nullable. CalcLength members still need to be nullable.

(It's annoying that our legacy behavior is for attributes to use "null" as the unspecified value, rather than "undefined". I assume this is one of those Java legacies.)

@shans
Copy link
Contributor

shans commented Apr 7, 2016

d04d175

@shans shans closed this as completed Apr 7, 2016
majido pushed a commit to majido/css-houdini-drafts that referenced this issue Aug 27, 2018
* fixed: wrong camelCase: KeyFrameEffect -> KeyframeEffect
* fixed typo: WorklerAnimation -> WorkletAnimation
* added missing CSS object, and
* updated index.html
bfgeek pushed a commit that referenced this issue Sep 6, 2018
…on (#801)

* Fixed typos and mistakes in code examples. (#107)

* fixed: wrong camelCase: KeyFrameEffect -> KeyframeEffect
* fixed typo: WorklerAnimation -> WorkletAnimation
* added missing CSS object, and
* updated index.html

* Add [Exposed] to interfaces (#109)

Add appropriate [Exposed] to interfaces.

https://heycam.github.io/webidl/#idl-interfaces says:
"Non-callback interfaces which are not annotated with a [NoInterfaceObject] extended attribute, and callback interfaces which declare constants must be annotated with an [Exposed] extended attribute."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants