Skip to content

Eventproxy Assignments

Congressional Leaders Announce Appointments to New Budget and Appropriations Reform Panel

March 5, 2018—House and Senate leaders announced appointments to the Joint Select Committee on Budget and Appropriations Process Reform. The temporary panel was created by the Bipartisan Budget Act of 2018 [See Washington Highlights, Feb. 9] and ordered to “provide recommendations and legislative language that will significantly reform the budget and appropriations process.” Additionally, the joint committee must produce a report no later than Nov. 30, 2018.

House Speaker Paul Ryan (R-Wis.) Feb. 22 announced the appointment of Reps. Steve Womack (R-Ark.), Pete Sessions (R-Texas), Rob Woodall (R-Ga.), and Jodey Arrington (R-Texas). Similarly, House Democratic Leader Nancy Pelosi (D-Calif.) Feb. 23 announced the appointment of Reps. Nita Lowey (D-N.Y.), John Yarmuth (D-Ky.), Lucille Roybal-Allard (D-Calif.), and Derek Kilmer (D-Wash.) to the new budget and appropriations panel.

For the Senate’s assignments, Senate Majority Leader Mitch McConnell (R-Ky.) Feb. 27 announced the appointment of Sens. Roy Blunt (R-Mo.), David Perdue (R-Ga.), James Lankford (R-Okla.), and Joni Ernst (R-Iowa) while Senate Minority Leader Chuck Schumer (D-N.Y.) Feb. 26 announced that Sens. Sheldon Whitehouse (D-R.I.), Michael Bennet (D-Colo.), Brian Schatz (D-Hawaii), and Mazie Hirono (D-Hawaii) will serve on the panel for the Senate Democrats.

Contact:

Tannaz Rasouli
Sr. Director, Public Policy & Strategic Outreach
Telephone: 202-828-0525
Email: trasouli@aamc.org

Joseph Bañez
Legislative Analyst
Telephone: 202-739-2995
Email: jbanez@aamc.org

.

Subscribe to Washington Highlights

Subscribe to RSS

Washington Highlights, a weekly electronic newsletter, features brief updates on the latest legislative and regulatory activities affecting medical schools and teaching hospitals.

For More Information

Jason Kleinman
Sr. Legislative Analyst, Govt. Relations
Telephone: 202-903-0806
Email: jkleinman@aamc.org

Mucking about with the DOM

We know that is responsible for mutating the one DOM node to match a vnode. But most of the actual manipulation is done through helper functions defined in . There are a couple easy ones, for removing a node from the DOM:

/** Removes a given DOM Node from its parent. */
export function removeNode(node) {
let p = node.parentNode;
if (p) p.removeChild(node);
}

There’s another for safely setting DOM attributes without throwing exceptions: (although I wonder if it should at least log these to let the developer know)

/** Attempt to set a DOM property to the given value.
* IE & FF throw for certain property-value combinations. */
function setProperty(node, name, value) {
try {
node[name] = value;
} catch (e) { }
}

And a wrapper for DOM event handlers that exposes a global hook for normalizing events, if you should desire. (We’ll see why the indirection of is useful in just a little while.)

/** Proxy an event to hooked event handlers
* @private */
function eventProxy(e) {
return this._listeners[e.type](
options.event && options.event(e) || e);
}

But the real business of this file is in the exported function , which is used to set an arbitrary key/value pair from a vnode’s props onto a real DOM node. The function’s signature includes some extra information that is sometimes needed, like the vdom value previously assigned for this attribute, and whether we’re inside an SVG context:

/** Set a named attribute on the given Node, with special behavior for some names and event handlers.
* If `value` is `null`, the attribute/handler will be removed.
* @param {Element} node An element to mutate
* @param {string} name The name/key to set, such as an event or attribute name
* @param {any} old The last value that was set for this name/node pair
* @param {any} value An attribute value, such as a function to be used as an event handler
* @param {Boolean} isSvg Are we currently diffing inside an svg?
* @private
*/
export function setAccessor(node, name, old, value, isSvg) {

The function then proceeds to consider a bunch of different cases for the and that we want to set on the node.

Preact supports setting classes with the prop key or , so it normalizes those to the same name. It also supports setting classes via an object, like so it converts objects to a string if we’re setting the class:

if (name==='className') name = 'class';if (name==='class' && value && typeof value==='object') {
value = hashToClassName(value);
}

The attribute is used by the diffing algorithm but not intended to be rendered to the DOM, so it’s ignored:

if (name==='key') {
// ignore

If we’re setting the class, it’s already normalized to a string so just set it:

} else if (name==='class' && !isSvg) {
node.className = value || '';
}

If we’re setting the node’s styles, we first need to clear off the previous styles and then set the new ones, either via a string or an object of property/value pairs. Note the bit about . That’s so you can use numerical values like and Preact will automatically add the for you, unless the property name is in that list of non-dimensioned property names.

else if (name==='style') {
if (!value || isString(value) || isString(old)) {
node.style.cssText = value || '';
}
if (value && typeof value==='object') {
if (!isString(old)) {
for (let i in old) if (!(i in value)) node.style[i] = '';
}
for (let i in value) {
node.style[i] =
typeof value[i]==='number' && !NON_DIMENSION_PROPS[i] ?
(value[i]+'px') : value[i];
}
}
}

Next up is dangerously setting a string as inner html:

else if (name==='dangerouslySetInnerHTML') {
if (value) node.innerHTML = value.__html || '';
}

Setting event handlers is an interesting optimization. Rather than re-set event handlers every time we render, which could be expensive, we save a map from event names to user-defined handlers on the DOM node as . Then we only add/remove DOM event listeners if the set of events that is being listened to changes. The actual event handler attached to the DOM is just , which we saw above, which looks into our map of event handlers to call the right one.

else if (name[0]=='o' && name[1]=='n') {
let l = node._listeners || (node._listeners = {});
name = toLowerCase(name.substring(2)); // adding a callback to a new event
if (value) {
if (!l[name]) node.addEventListener(name, eventProxy,
!!NON_BUBBLING_EVENTS[name]);
} // removing a callback from an event no longer listened to
else if (l[name]) {
node.removeEventListener(name, eventProxy,
!!NON_BUBBLING_EVENTS[name]);
}
l[name] = value;
}

If we haven’t hit on the property name yet, then it might be a plain old DOM property, which we set directly, using the helper that we saw earlier. If the value is , , or , then we just remove the attribute.

else if (name!=='list' && name!=='type' && !isSvg && name in node) {
setProperty(node, name, value==null ? '' : value);
if (value==null || value===false) node.removeAttribute(name);
}

There’s one final case: SVG attributes. For these, we need to use the special namespace-aware attribute methods:

else {
let ns = isSvg && name.match(/^xlink\:?(.+)/);
if (value==null || value===false) {
if (ns)
node.removeAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1]));
else
node.removeAttribute(name);
}
else if (typeof value!=='object' && !isFunction(value)) {
if (ns)
node.setAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1]), value);
else
node.setAttribute(name, value);
}
}

And that’s it. Those are the special cases that of attributes that can be set to the DOM from keys in the vnode’s props. To review, the cases Preact supports are:

  • and , with either a string or an object, to set the class
  • , either a string or an object, to set style properties
  • for setting a string as the innerHTML of a node
  • event handlers via
  • DOM properties
  • SVG attributes

Now that we understand what does to set individual DOM attributes, let’s see how it’s used. It’s called by , which lives in the vdom diffing code and is called by as it changes a node to match a vdom specification. That’s this part of our diagram:

The source of is pretty simple. It runs through any attributes in the previous state but not the current one and removes them, then goes through all the attributes in the current state and sets them. But there are a couple slightly crazy bits we need to remember.

First, certain attributes don’t even get sent to because we don’t want to even try to set them on the DOM. and get filtered out, since we never want to try to render them. Then there’s one additional test the attribute has to pass:

// either it's a new attribute, or ...
!(name in old) ||
// its value is not equal to ...
attrs[name]!==
// if it's a DOM form value
(name==='value' || name==='checked' ?
// then the value on the DOM node
dom[name] :
// otherwise, the previous version of the prop
old[name]))

That boolean expression had me scratching my head for a while. But what it’s trying to say is:

  • If the current value is the same as the previous one, there’s no need to set it again.
  • Unless it’s or , because those might have been changed by user interaction since the last render. So to see if we need to re-set this attribute, we need to check against what’s on the real node, not what’s in the old props.
  • And unless this prop wasn’t in the old props, because then we definitely need to re-render it and can avoid running the logic above.

That’s it for the first bit of complexity about , how it decides which attributes to send on to .

The second bit of complexity is an extra responsibility that has. When removing attributes that were in the old state but not the new one, calls this way:

setAccessor(dom, name, old[name], old[name] = undefined, svgMode);

And when updating an attribute, it calls it this way:

setAccessor(dom, name, old[name], old[name] = attrs[name], svgMode);

Note that in both places, it doesn’t just pass in a value to set for this attribute on the DOM node, but also mutates the object to have the new value. To understand why, we need to understand another little detail that we haven’t gotten to yet. In order to do faster diffing, and especially in order to respect the property when diffing children, Preact needs access to the vnode properties used the last time it rendered a specific DOM node. So it caches these properties as an attribute on the node. And in this head-scratching code above, it turns out that isn’t just an object of the old attributes. It’s actually the cache of attribute properties that is saved on the DOM node. Which means that is, in this weirdly indirect way, also responsible for updating the prop cache as it updates the DOM attributes. (Remember, this is some seriously-golfed code. Don’t write your application logic like this.)

We already knew that is responsible for updating a DOM node to match a vdom tree. And now we know all the details of how it makes the attributes on the DOM node match the properties of the vnode. That’s a big chunk of the codebase, so savor the feeling of understanding it! Go get some chocolate or stand up and stretch. Seriously. The rest will still be here when you get back.