function constValue (cnt)
{
    if (cnt.type === "null") return null;
    if (cnt.type === "NaN") return NaN;
    if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;
    if (cnt.type === "number") return +cnt.value;
    return cnt.value;
}
Notes for people who want to edit this file (not just use it as a library):

Most of the interesting stuff happens in the derived classes of IdlObject,
especially IdlInterface.  The entry point for all IdlObjects is .test(),
which is called by IdlArray.test().  An IdlObject is conceptually just
"thing we want to run tests on", and an IdlArray is an array of IdlObjects
with some additional data thrown in.

The object model is based on what WebIDLParser.js produces, which is in turn
based on its pegjs grammar.  If you want to figure out what properties an
object will have from WebIDLParser.js, the best way is to look at the
grammar:

  https://github.com/darobin/webidl.js/blob/master/lib/grammar.peg

So for instance:

  // interface definition
  interface
      =   extAttrs:extendedAttributeList? S? "interface" S name:identifier w herit:ifInheritance? w "{" w mem:ifMember* w "}" w ";" w
          { return { type: "interface", name: name, inheritance: herit, members: mem, extAttrs: extAttrs }; }

This means that an "interface" object will have a .type property equal to
the string "interface", a .name property equal to the identifier that the
parser found, an .inheritance property equal to either null or the result of
the "ifInheritance" production found elsewhere in the grammar, and so on.
After each grammatical production is a JavaScript function in curly braces
that gets called with suitable arguments and returns some JavaScript value.

(Note that the version of WebIDLParser.js we use might sometimes be
out-of-date or forked.)

The members and methods of the classes defined by this file are all at least
briefly documented, hopefully.