Tab Completion

I'm Tab Atkins Jr, and I wear many hats. I work for Google on the Chrome browser as a Web Standards Hacker. I'm also a member of the CSS Working Group, and contribute to several other working groups in the W3C.
Listing of All Posts

Why I'm Excited about Names in JavaScript

There's a ton of exciting activity taking place in TC39, which is the standards group responsible for handling JavaScript (known as ECMAScript there, as ECMA is the standards body that TC39 is part of). One in particular that I like quite a bit is Names. It's not very obvious why this is so good, though, or what advantages these have over other, similar proposals or similar features in other languages.

The Hell are Names?

You know how you access properties on an object with strings? In the Names proposal, you can additionally use a Name object to access properties. This is important, because Name objects are unique and unforgeable. In other words, unless someone gives you the Name object, there is no possible way for you to access that property.

There's another aspect, which is the ability to make some of these Names private. I'll distinguish the two by calling the original thing Unique Names, and the private things Private Names.

If you're familiar with the term "Object Capabilities", Names are a building block for that technology.

What's the Use of a Unique Name?

Having a guaranteed-unique name is wonderful. Many things that are cumbersome or even practically impossible without them become trivial once you have them.

If you're familiar with Lisp, unique names generated with GENSYM are absolutely necessary to write robust macros; without them, you stand a decent chance of accidentally colliding with existing names and breaking code in mysterious ways.

In JS, Unique Names are great for adding "interface" properties to an object. Let's say you define an Iterator interface, plus a bunch of functions that take Iterators and do cool stuff with them. When someone passes you an object, you want to check if it's an Iterator, and if not, ask it to give you an Iterator. For example, if someone passes you a string, you should be able to ask it for an iterator over the characters.

How do you ask for this, though? The simple answer is to say that objects need to have a particular method, getIterator() or __iterator() or something, that returns an iterator. This isn't great, though - what if they already have a property by that name that does something else?

Another way, if you have control over the language, would be to define a set of functions on something the language controls, like Object.setIterator(), Object.getIterator(), and Object.deleteIterator(), which maintain an internal map of classes to iterators. This is just plain cumbersome and ugly, though.

Using a Unique Name, though, this is easy! You just create a special Name and store it somewhere publicly accessible. When someone wants their object to expose an iterator, they just grab the Name you've created, and store their method using it. This'll look something like:

/* library code */
let Iterator = {
  ...
  getIterator: new Name()
}

/* user code */
function myCoolObject() { ... }
myCoolObject.prototype[Iterator.getIterator] = function(){...}

That's it! In the library, whenever a function that expects an iterator is passed something else, it'll first poke at the object using the Iterator.getIterator Name, and if it finds a function there, it'll just call that to extract an iterator.

The benefit of this little bit of indirection is that it's impossible for the user's class to have a property-collision with the Iterator library's property.

One can do even more extreme things, too. What if you want an object to be an iterator, rather than just provide one? (Analogous to the difference between PHP's Iterator and IteratorAggregate interfaces.) You need the object to expose a couple of properties; at minimum, you probably want something like .current, .valid, and .moveNext(). But, again, the object might already use those properties for something else! (This is especially true for names like this - 'current' and 'valid' are reasonably common property names.) Again, though, you can just use Unique Names for this, and in fact the method is exactly the same as before - just create some Names, store them in an easy-to-reach place, and then other classes can just grab and use those Names to store their implementations for you.

A final use of Unique Names - typing! Right now, there are two decent ways to ask an object what type it is - examine its prototype chain, or do "duck typing" (see if it exposes the properties you expect for the given type). Neither of these are great. Prototype-chain examining means you have to use inheritance for your objects, the sins of which are well-documented elsewhere. Duck typing is unreliable because objects can accidentally expose the properties you want without actually working the way you expect. Using Unique Names, though, we can resolve this. Again, just create a Unique Name and stash it somewhere. When an object wants to declare it's your type, it just takes that Name and sets it to true on itself. BAM, type checking is easy - if you check the property on a random object, you'll either get undefined or true based on whether it claims to be the type or not.

I'm sure there are plenty of other cool things in this vein, but my brain keeps getting twisted back to iterators, so you'll have to come up with them on your own.

Okay, But What About Those Private Names?

Private Names are just like Unique Names, except they've got some extra protections to avoid exposing them accidentally.

You'd think, from the name, that these might be useful for making private properties in JS, but you'd be wrong. JS already has private properties, through closures[1]:

(function(){
  let privateVar = 'foo';

  function Bar() {
    console.log("Hahaha, only I have access to the privateVar!");
    console.log("But I guess you can look at it:");
    console.log(privateVar);
  }
})();

What Private Names are good for is making protected variables, except ridiculously more flexibly and powerfully.

In most OO languages, if you want to have a property that's hidden to most, but available to some classes other than yourself, you have to mark it protected, and the other classes have to inherit from you. This is pretty horrible, because wanting to use something's private variables is not the same thing as wanting to inherit from it. Some languages like C++ have workarounds for this (the friend keyword in C++), but they're all pretty hacky.

Private Names let you hide properties from the public, and expose them to whoever you want - you just have to give them the corresponding Names. You can even expose different sets of properties to different consumers, just by handing out different subsets of your private Names. There's no need to tie this functionality into inheritance.

Here's yet another cool use. I'll assume you know about Proxies, those cool new JS things that let one object pretend to be another object by supplying functions that get called whenever you try and get a property, set a property, etc. on the Proxy. With that functionality, you can hide all details of what's going on underneath normal-looking syntax.

One use for Proxies is to supply someone with a limited-functionality version of an object. Make a Proxy object, store your original object in it, and make the proxy transparently supply the original object's properties if they're on a limited list, and block them (as if they aren't there at all) otherwise. This lets you supply a lesser interface for an object with a minimum of fuss, while still letting the actual object access all of itself.

This is somewhat limited, though. You have to hide the original object inside the Proxy object (or else there's not much point). Right now, that means you have to use a closure variable, as demonstrated above, to hide it so that only the Proxy's own functions can access it. This means, though, that if you pass the limited-functionality object back to the original API that gave it out, it can't extract the full-powered object back out again! (Any method you supply to allow it to do so would allow someone else to do this as well.) With Private Names, though, this concern disappears. You can just store the original object on the Proxy with a Private Name (storing the name itself both in your original API, and in a closure variable in the Proxy object), and then pull it back out again later with the same name, but no one else can access it! (Dave Herman points out another method to accomplish this.[2])

But What Actually Makes Private Names Different From Unique Names?

You're right, hidden-interlocutor-in-control-of-this-post's-titles, everything I described above can be done with Unique Names as well. The difference between the two is that Private Names have some different defaults set, and act differently with Proxies (in a different scenario than what I described above).

For starters, Unique Names are just ordinary properties; they just use Name objects instead of strings for their name. So, if you use a for-in loop to iterate through all the properties, you'll see properties that use Unique Names alongside all the string-named ones. On the other hand, properties using Private Names are automatically non-enumerable.

The other difference is their behavior with Proxies. When you set up a Proxy, you assign functions to several operations, like "get a property", which is called whenever someone performs that action on the Proxy. In the case of getting/setting a property, your function is passed the name of the property that's being get/set. If someone attempts to access a property on a Proxy using a Private Name, though, and the system naively passed it through, it would "leak" the name - the owner of the Proxy would then have your Private Name and could use it themselves.

Instead, Private Names automatically get a corresponding Unique Name when they're created. This is stored in the Private Name's .public property. When a Proxy attempts to deal with a Private Name, it instead receives the Private Name's public property. If the Proxy already has access to the Private Name, it can compare the .public is has with what it's received, but if it doesn't, then no private information is leaked. There's no linkage back from the public property to the corresponding Private Name; you can't use the Unique Name stored in the .public property for anything except comparisons.

Care to Wrap it Up?

In conclusion, Names are awesome. They let you do a lot of cool things that are difficult/hacky/impossible to do right now, and they're the building blocks for some important security tools like Object Capabilities.

Here's hoping they make it into JS in the nearish future!

[1]: Dave Herman, author of the current Private Names proposal, points out that Private Names do make private variables easier. If you want a per-instance closure variable, you also have to define all your methods per-instance, rather than defining them once on the prototype. This is hugely costly if you then create a lot of instances. Private Names let you accomplish this without pain:

(function(){
  let key = new Name();
  function Thingy(x) {
    this[key] = x;
  }
  Thingy.prototype = {
    doStuff: function() { ... this[key] ... }
  };
})();

[2]: Dave Herman points out another solution. Remember that Object.get/set/deleteIterator() thing I talked about earlier, where you maintain a hidden table of associations? Using WeakMaps, another upcoming feature which, among other things, lets you create a dictionary with object keys, you can create a side-table linking a given Proxy to its original object in the same way. Whether this is easier or harder than using Private Names may vary based on the individual case.

Last updated:

CSS Spec Terms, for Future Reference

I accidentally use some CSS terms interchangeably sometimes. I try to maintain discipline here, but not everyone even knows what the correct terms are, so they can't make themselves do it right.

I'll add to this list in the future as I come up with more stuff that occasionally confuses me.

rule or ruleset: A selector + braces combo, or an at-rule.

declaration block: A sequence of declarations.

declaration: A property + colon + value combo.

property value: The entire value of a property.

component value: A single piece of a property value. Like the 5px in text-shadow: 0 0 5px blue;. Can also refer to things that are multiple terms, like the 1-4 terms that make up the background-size portion of the background shorthand.

term: The basic unit of author-facing CSS, like a single number (5), dimension (5px), string ("foo"), or function. Officially defined by the CSS 2.1 grammar (look for the 'term' production)

outer : Refers to the margin box.

inner : Refers to the content box.

start/end/before/after: Refers to the logical directions, which are dependent on the 'direction' and 'writing-mode' properties. start and end are in the "inline" axis, the axis that a line of text is laid out in (horizontal in English text). Perpendicular to that, before and after are in the "block" axis, the axis that block elements are laid out in (vertical in English text).

simple selector: A single atomic selector, like a type selector, an attr selector, a class selector, etc.

compound selector: One or more simple selectors without a combinator. div.example is compound, div > .example is not.

complex selector: One or more compound selectors chained with combinators.

combinator: The parts of selectors that express relationships. There are four currently - the space (descendant combinator), the greater-than bracket (child combinator), the plus sign (next sibling combinator), and the tilda (following sibling combinator).

sequence of selectors: One or more of the named type of selector chained with commas.

inline: Something that participates in inline layout (it goes into lineboxes) and will break across lines, like <span>.

atomic inline: Something that participates in inline layout but doesn't break across lines, like <img> or anything with display:inline-block.

inline-level: Either inline or atomic inline.

block container: Something whose insides are formatted with block layout, like <div> or anything with display:inline-block.

block-level: Something that participates in block layout, like <div>.

block: A block-level block container.

Last updated:

TopatoCo is the Best, and You Should Buy Everything They Have

I just got this email today:

Someone is About to Get a Package From TopatoCo!

And that someone is Tab Atkins Jr! Tab is about to get a package in the mail from TopatoCo, former freelance hovercraft pilot training center turned world famous webcomic merchandise distributor! Basically we just wanted to let you know that your order 196811 has shipped and the tracking information follows (if available). Thank you so much!

Shipped on 9/16/2011 using USPS First Class: XXXXXXXXXXXXXXXXXXXX

If the shipment is USPS International Priority or First Class, the number above is NOT an actual tracking number, it is only a Customs ID for use in the event of a lost > package. Keep in mind none of these numbers become active in the UPS/USPS system until they actually grab them from us, which can take 24 hours and even longer on weekends.

USPS packages within the United States should arrive in 2-5 days, and UPS packages in the exact amount of time the tracking number indicates. Canadian deliveries should be expected anywhere between three days and two weeks, mostly depending on border activity.

If your package is destined for a distant, magical land it can take up to four weeks depending on how seriously the Customs Agent takes their job. We strongly urge you to familiarize yourself on any weird silliness your local mail delivery place might pull when receiving and delivering packages from the US Postal Service. USPS tracking is not available for international destinations (unless you paid for Express shipping), but all packages have Customs IDs that can sometimes be used to determine the approximate location of mischevious packages. If you need more information, please visit http://www.topatoco.com/help/ or write to support@topatoco.com. Thanks for supporting independent artists on the Inter-Tubes of CyyyyberSpace!

TopatoCo provides storefront and/or shipping services for the following independent creators. Learn more about them at http://www.topatoco.com/creators/

Sincerely, Holly, Kaliis, Jeffrey, Lucid John, and Wolfman Green http://www.topatoco.com

"TopatoCo. Occasionally Thinking About the Children, Then Quickly Thinking of Something Else."

This is why I love TopatoCo and all the wondrous things they sell. They sold me the always-popular and oh-so-comfy Fat Pony Tshirt, and this most recent email is announcing that I'm soon going to receive my personalized copy of the Dresden Codak Primer with some sort of sketch in it! Yay!

So yeah, go to TopatoCo and give them all your money. They're starving artists, and you're a good person, right? Good people support the arts.

Last updated:

Flexbox is Dead, Long Live Flexbox!

I've been meaning to write this post for a month. I'm bad at time management.

If you've been following my blog over the last year or so, you'll know that I'm the active editor of the CSS Flexbox spec. I picked up this spec because I thought the original spec was too close of a direct translation from XUL, and that we could do better. Specifically, I thought we could rewrite the spec to use normal box-model properties (width, height, padding, margin) and just directly make them flexible. If you look back through my archives you'll see several attempts at rewrites in this vein.

Well, the experiment has ended. The spec has returned to a form very similar to the original. I'm a little sad about this, but it's the right choice. Unfortunately, if you limit yourself to making the box-model properties flexible, several useful things are simply impossible, and several others are overly difficult.

Specifically, flex-pack: distribute can't be done without screwing around with margins on :first/last-child, like you have to do to today when using floats for similar purposes. flex-align: baseline is completely impossible. All of the flex-pack properties are impossible if the flexbox is multi-line. And don't even get me started on controlling the distribution/alignment of lines in a multi-line flexbox. The lines aren't real boxes, so you can't access them to tweak their margins, etc. unless we add extra pseudo-elements. Once you need one special property to control the alignment, it starts making more sense to handle all of the alignment in that property.

There have still been some wins. I've merged the old box-direction and box-orientation properties into a single flex-flow property. (The syntax for flex-flow looks a little scary, but it's pretty simple in practice.) I've axed the box-flex-group property, while box-ordinal-group has been renamed to the much friendlier flex-order. And most importantly, width and height are still directly flexible, rather than deferring to a separate box-flex property. Multiple authors (including the CSSWG's own chairman!) have been confused by the way box-flex works over the years. I'm very happy that stayed dead.

An additional silver lining is that Flexbox and Grid Layout now share many concepts, so learning one of them will help you understand the other. I'm extremely happy about this; the new layout models need to be as simple and easy as possible to help justify their additions, and now that these two are compatible, any future layout models have a very good reason to also be compatible. Yay! I'm going to continue to work on getting them to share concepts, and ensure that the general layout algorithm is consistent between the two so things are predictable.

The spec is pretty stable now, and I'm happy about that. I've got a few outstanding issues we're currently discussing in the group about the meaning of a few properties (in particular, if we can simplify flex-flow, and exactly how the center values work in the three alignment properties). Once we resolve those, it's simply a matter of me turning my sketch of a layout algorithm into something detailed and normative, like what I had before. Then I can release a WD, hopefully get that to CR, write tests, and continue on from there. Yay!

If you have comments on the draft, feel free to either email me personally or email www-style@w3.org with the subject starting with "[css3-flexbox]".

Last updated:

Stacked Layout Proposal

[As usual, this is a personal draft/proposal, and carries no endorsement or support from the CSSWG.]

The CSS2.1 layout modes were primarily designed for laying out documents, not webapps. Webdevs have gone to heroic efforts to bend the 2.1 layout modes to actually work for webapps and have done some amazing things, but it shouldn't be that hard. Two relatively new specs coming out of the CSSWG for CSS3 are addressing this problem - Flexbox and Grid Layout - but there are a few more places where we could solve a problem with a simple, targetted layout solution.

One in particular is stacked layout, where multiple elements are stacked atop each other, and only the topmost is shown at any one time. This is used quite commonly in "tabbed" displays, for example, like your browser window.

Can This Be Done via Existing Approaches?

A stack can be thought of as similar to a flexbox that happens to be aligned on the Z axis, rather than the X or Y. However, attempting to graft this into flexbox doesn't actually work well. You need a lot of new controls to make it work properly, such that you haven't actually gained anything. It's just not worth the complexity.

Attempting to graft this into Grid is a bit easier. When you set display:grid, the initial value of grid-rows and grid-columns set up a single cell that spans the element, and the initial value of grid-row and grid-column places all the grid items in the cell at (1 1). So, just be setting the display, you get all the children stacked together, with grid-layer controlling which element is on top. This still has a few problems, though. The elements are literally stacked on top of each other, so if they're different sizes or partially transparent you'll see the lower elements. Most of the time you actually want the "lower" elements completely hidden.

display:stack

So, this needs to be done as a separate layout mode. It seems like we can get away with something really simple, luckily.

Start with a simply display:stack addition. It would borrow a lot of language from Flexbox or Grid in terms of defining children as being "stack items", handling block formatting contexts, etc.

Add a property for controlling the order. We can either borrow from Flexbox and get stack-order or borrow from Grid and get stack-layer. Alternately, since we're only showing a single item from the stack, we could set up a simple property that just accepted, say, top and auto - it shows the first element in source order with top set. Another possible direction is a property set on the stack itself giving an index into its stack items, denoting which one is on top. That has the advantage of only declaring a single "top" element. This needs some thought.

Add a property for controlling the size of the stack. By default, the stack could size itself to the size of its widest and tallest children, but the property could instead make it size itself according to the current "top" child.

Finally, add properties for aligning children within the stack, when they're smaller than the stack element itself. Grid's already got a pair of alignment properties that do what we want; we'd just have to change the names.

Attaching Tabs to the Stack

The only bit that gets complicated is that most stacks expose a set of tabs connected to the stack items, so that selecting a tab promotes the associated stack item to the top. This sort of connection is hard to do in CSS, so I'm not sure how we'd do it. It's possible that this is kept in JS, and we just handle the layout of the stack itself in CSS.

If we did do this in CSS, though, here's some initial ideas:

Another display type, like display:stack-tab, for declaring an element to be a tab. If the tab is a direct child of a stack, it's automatically associated with the following stack item. Otherwise, if it's inside of a stack item, it's associated with that stack item. Otherwise, it's equivalent to display:block.

The stack itself would then grow two child boxes - one for the tabs, and one for the stack items. The tabs would automatically be moved to the tab container (possible through some automatic Regions machinery) where they can be styled normally. The position of the tab container would be controlled by another property. The container is accessible through a pseudo-element and can be styled normally as well. Default it to display:flexbox with a good direction, so the tabs can reorder themselves with a simply flex-order declaration.

The only remaining magic is setting one of the stack items to be the top based on activating tabs. This lends some weight to the "property on the stack" approach for choosing the top stack item - rather than a numeric index, you can just set "active-tab" as the value, and whenever a tab is "activated" (whatever that means), it changes the top stack item. The tabs themselves would also need some way to detect when they're "active", probably via a pseudoclass like :active-tab.

Doing this more than doubles the complexity of the spec, unfortunately, and it still might not be ideal for all cases. Spec design is hard!

Last updated:

Older Posts