7.4. Convert a value to a key

The steps to convert a value to a key are as follows. These steps take two arguments, an ECMAScript value input, and an optional set seen. The result of these steps is a key or invalid, or the steps may throw an exception.

  1. If seen was not given, let seen be a new empty set.

  2. If input is in seen return invalid.

  3. Jump to the appropriate step below:

    If Type(input) is Number

    1. If input is NaN then return invalid.

    2. Otherwise, return a new key with type number and value input.

  1. If input is a [Date](https://tc39.github.io/ecma262/#sec-date-objects) (has a \[\[DateValue\]\] internal slot)
  2. 1. Let ms be the value of inputs \[\[DateValue\]\] internal slot.
  3. 2. If ms is NaN then return invalid.
  4. 3. Otherwise, return a new [key](#key) with [type](#key-type) *date* and [value](#key-value) ms.
  5. If [Type](https://tc39.github.io/ecma262/#sec-ecmascript-data-types-and-values)(input) is String
  6. 1. Return a new [key](#key) with [type](#key-type) *string* and [value](#key-value) input.
  7. If input is a [buffer source type](https://www.w3.org/TR/WebIDL-1/#dfn-buffer-source-type)
  8. 1. Let octets be the result of running the steps to [get a copy of the bytes held by the buffer source](https://www.w3.org/TR/WebIDL-1/#dfn-get-buffer-source-copy) input. Rethrow any exceptions.
  9. 2. Return a new [key](#key) with [type](#key-type) *binary* and [value](#key-value) octets.
  10. If [IsArray](https://tc39.github.io/ecma262/#sec-isarray)(input)
  11. 1. Let len be [?](https://tc39.github.io/ecma262/#sec-algorithm-conventions) [ToLength](https://tc39.github.io/ecma262/#sec-tolength)( [?](https://tc39.github.io/ecma262/#sec-algorithm-conventions) [Get](https://tc39.github.io/ecma262/#sec-get-o-p)(input, "`length`")).
  12. 2. Add input to seen.
  13. 3. Let keys be a new empty list.
  14. 4. Let index be 0.
  15. 5. While index is less than len:
  16. 1. Let hop be [?](https://tc39.github.io/ecma262/#sec-algorithm-conventions) [HasOwnProperty](https://tc39.github.io/ecma262/#sec-hasownproperty)(input, index).
  17. 2. If hop is false, return invalid.
  18. 3. Let entry be [?](https://tc39.github.io/ecma262/#sec-algorithm-conventions) [Get](https://tc39.github.io/ecma262/#sec-get-o-p)(input, index).
  19. 4. Let key be the result of running the steps to [convert a value to a key](#convert-a-value-to-a-key) with arguments entry and seen.
  20. 5. [ReturnIfAbrupt](https://tc39.github.io/ecma262/#sec-returnifabrupt)(key).
  21. 6. If key is invalid abort these steps and return invalid.
  22. 7. Append key to keys.
  23. 8. Increase index by 1.
  24. 6. Return a new [array key](#array-key) with [value](#key-value) keys.
  25. Otherwise
  26. Return invalid.

The steps to convert a value to a multiEntry key are as follows. These steps take one argument, an ECMAScript value input. The result of these steps is a key or invalid, or the steps may throw an exception.

  1. If IsArray(input), then:

    1. Let len be ? ToLength( ? Get(input, “length“)).

    2. Let seen be a new set containing only input.

    3. Let keys be a new empty set.

    4. Let index be 0.

    5. While index is less than len:

      1. Let entry be Get(input, index).

      2. If entry is not an abrupt completion, then:

        1. Let key be the result of running the steps to convert a value to a key with arguments entry and seen.

        2. If key is not invalid or an abrupt completion, add key to keys if there are no other members of keys equal to key.

      3. Increase index by 1.

    6. Return a new array key with value set to a list of the members of keys.

  2. Otherwise, return the result of running the steps to convert a value to a key with argument input. Rethrow any exceptions.

These steps are similar to those to convert a value to a key but if the top-level value is an Array then members which can not be converted to keys are ignored, and duplicates are removed.

For example, the value [10, 20, null, 30, 20] is converted to an array key with subkeys 10, 20, 30.