No description, website, or topics provided.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
readme.md

readme.md

  • enum is a new LexicalDeclaration binding form, similar to let or const.

  • typeof enum is object; similar to Array, it's just a special Object (more below)

  • EnumDeclaration with no BindingIdentifier creates const bindings corresponding to each EnumEntryName:

    enum {
      SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
    }

    Is equivalent to:

    const SUNDAY = 0;
    const MONDAY = 1;
    const TUESDAY = 2;
    const WEDNESDAY = 3;
    const THURSDAY = 4;
    const FRIDAY = 5;
    const SATURDAY = 6;
  • EnumDeclaration or EnumExpression with a BindingIdentifier creates:

    • A proto-less, frozen object;

    • Creates PropertyName corresponding to each EnumEntryName:

      enum DaysOfWeek {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
      }
      
      const DaysOfWeek = enum {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY    
      };

      Is approximately* equivalent to:

      const DaysOfWeek = Object.freeze(
        Object.create(null, {
          [Symbol.enumSize]: {
            // Specification can define better semantics for deriving 
            // and storing the size of the enum object (internal slot)
            value: 7
          }, 
          [Symbol.iterator]: {
            * value() {
              // Specification can define better semantics for deriving 
              // and storing keys and values (internal slot)
              let keys = Object.keys(DaysOfWeek); 
              let values = Object.values(DaysOfWeek);
              let index = 0;
              while (index < keys.length) {
                yield [keys[index], values[index]];
                index++;
              }
            }
          },
          SUNDAY: { value: 0, enumerable: true },
          MONDAY: { value: 1, enumerable: true },
          TUESDAY: { value: 2, enumerable: true },
          WEDNESDAY: { value: 3, enumerable: true },
          THURSDAY: { value: 4, enumerable: true },
          FRIDAY: { value: 5, enumerable: true },
          SATURDAY: { value: 6, enumerable: true },
        })
      );
      
      for (let [day, value] of DaysOfWeek) { console.log(value, day) }
      
      /*
        0 SUNDAY
        1 MONDAY
        2 TUESDAY
        3 WEDNESDAY
        4 THURSDAY
        5 FRIDAY
        6 SATURDAY    
       */
  • EnumDeclaration or EnumExpression will set the value of each entry to an integer, starting at 0 and incrementing by 1 for each entry.

  • EnumDeclaration may have EnumEntryName inline assignment overrides. If an entry has an inline assignment, the default value is incremented as normal, but not used for that entry.

    enum {
      FOO, 
      BAR = _AssignmentExpression_, 
      BAZ, 
    }

    Is equivalent to:

    const FOO = 0;
    const BAR = _AssignmentExpression_;
    const BAZ = 2;

    EnumDeclaration (with BindingIdentifier) or EnumExpression example:

    enum Things {
      FOO, 
      BAR = _AssignmentExpression_, 
      BAZ, 
    }
    
    const Things = enum {
      FOO, 
      BAR = _AssignmentExpression_, 
      BAZ, 
    };

    Is approximately equivalent to:

    const DaysOfWeek = Object.freeze(
      Object.create(null, {
        /*
        Assume Symbol.enumSize and Symbol.iterator
         */
        FOO: { value: 0, enumerable: true },
        BAR: { value: _AssignmentExpression_, enumerable: true },
        BAZ: { value: 2, enumerable: true },
      })
    );

    Of course, this means that the value of an enum entry can be whatever you want it to be:

    // todo
  • EnumDeclaration may have ComputedPropertyName as EnumEntryName:

    • TODO: Am I sure about this?
    enum {
      FOO, 
      ["BAR"], 
      BAZ, 
    }

    Is equivalent to:

    const FOO = 0;
    const BAR = 1;
    const BAZ = 2;

    EnumDeclaration (with BindingIdentifier) or EnumExpression example:

    enum Things {
      FOO, 
      [Symbol(...)], 
      BAZ, 
    }
    
    const Things = enum {
      FOO, 
      [Symbol(...)], 
      BAZ, 
    };

    Is approximately equivalent to:

    const DaysOfWeek = Object.freeze(
      Object.create(null, {
        /*
        Assume Symbol.enumSize and Symbol.iterator
         */
        FOO: { value: 0, enumerable: true },
        [Symbol(...)]: { value: 1, enumerable: true },
        BAZ: { value: 2, enumerable: true },
      })
    );
  • EnumDeclaration may not have duplicate EnumEntryName:

    • These throw exceptions:

      enum {
        FOO, 
        FOO
      }
      enum {
        FOO, 
        ["BAR"], 
        BAR, 
      }
  • EnumDeclaration with an EnumValueMap to populate the values of the Enum:

    function EnumValueMap(key, index) {
      return 1 << index;
    }
    
    enum via EnumValueMap {
      SUNDAY,
      MONDAY,
      TUESDAY,
      WEDNESDAY,
      THURSDAY,
      FRIDAY,
      SATURDAY,
    }
    
    // Is equivalent to: 
    
    const SUNDAY    = EnumValueMap(SV(SUNDAY), 0);   // 0b00000001
    const MONDAY    = EnumValueMap(SV(MONDAY), 1);   // 0b00000010
    const TUESDAY   = EnumValueMap(SV(TUESDAY), 2);  // 0b00000100
    const WEDNESDAY = EnumValueMap(SV(WEDNESDAY), 3);// 0b00001000
    const THURSDAY  = EnumValueMap(SV(THURSDAY), 4); // 0b00010000
    const FRIDAY    = EnumValueMap(SV(FRIDAY), 5);   // 0b00100000
    const SATURDAY  = EnumValueMap(SV(SATURDAY), 6); // 0b01000000

    And the BindingIdentifier example:

    function EnumValueMap(key, index) {
      return 1 << index;
    }
    
    enum DaysOfWeekAsBits via EnumValueMap {
      SUNDAY,
      MONDAY,
      TUESDAY,
      WEDNESDAY,
      THURSDAY,
      FRIDAY,
      SATURDAY,
    }

    Is approximately equivalent to:

    const DaysOfWeekAsBits = Object.freeze(
      Object.create(null, {
        [Symbol.enumSize]: {
          // Specification can define better semantics for deriving 
          // and storing the size of the enum object (internal slot)
          value: 7
        }, 
        [Symbol.iterator]: {
          * value() {
            // Specification can define better semantics for deriving 
            // and storing keys and values (internal slot)
            let keys = Object.keys(DaysOfWeekAsBits); 
            let values = Object.values(DaysOfWeekAsBits);
            let index = 0;
            while (index < keys.length) {
              yield [keys[index], values[index]];
              index++;
            }
          }
        },
        SUNDAY: { value: EnumValueMap(SV(SUNDAY), 0), enumerable: true },
        MONDAY: { value: EnumValueMap(SV(MONDAY), 1), enumerable: true },
        TUESDAY: { value: EnumValueMap(SV(TUESDAY), 2), enumerable: true },
        WEDNESDAY: { value: EnumValueMap(SV(WEDNESDAY), 3), enumerable: true },
        THURSDAY: { value: EnumValueMap(SV(THURSDAY), 4), enumerable: true },
        FRIDAY: { value: EnumValueMap(SV(FRIDAY), 5), enumerable: true },
        SATURDAY: { value: EnumValueMap(SV(SATURDAY), 6), enumerable: true },
      })
    );
    
    for (let [day, value] of DaysOfWeekAsBits) { console.log(value, day) }
    
    /*
      0b00000001 SUNDAY
      0b00000010 MONDAY
      0b00000100 TUESDAY
      0b00001000 WEDNESDAY
      0b00010000 THURSDAY
      0b00100000 FRIDAY
      0b01000000 SATURDAY    
     */

    WebIDL could specify its enum as using a default EnumValueMap; ie. https://heycam.github.io/webidl/#idl-enumeration might update its definition:

    An enumeration is a definition (matching Enum) used to declare a type whose valid values are a set of predefined strings.

    To:

    An enumeration is a definition (matching Enum) used to declare a type whose valid values are a set of predefined strings.

    An ECMAScript implementation of WebIDL enum would use a String EnumValueMap.

    enum RTCPeerConnectionState via String { 
      new,
      connecting,
      connected,
      disconnected,
      failed,
      closed,
    };

    Is approximately equivalent to:

    const RTCPeerConnectionState =Object.freeze(
      Object.create(null, {
        [Symbol.enumSize]: {
          // Specification can define better semantics for deriving 
          // and storing the size of the enum object (internal slot)
          value: 6
        }, 
        [Symbol.iterator]: {
          * value() {
            // Specification can define better semantics for deriving 
            // and storing keys and values (internal slot)
            let keys = Object.keys(RTCPeerConnectionState); 
            let values = Object.values(RTCPeerConnectionState);
            let index = 0;
            while (index < keys.length) {
              yield [keys[index], values[index]];
              index++;
            }
          }
        },
        // Note that this case illustrates that it's ok for the 
        // for the second argument to be ignored.
        new: { value: String(SV(new)), enumerable: true },
        connecting: { value: String(SV(connecting)), enumerable: true },
        connected: { value: String(SV(connected)), enumerable: true },
        disconnected: { value: String(SV(disconnected)), enumerable: true },
        failed: { value: String(SV(failed)), enumerable: true },
        closed: { value: String(SV(closed)), enumerable: true },
      })
    );

* Approximately means that it doesn't fully represent all of the semantics.