7.4. Convert a value to a key

To convert a value to a key with an ECMAScript value input, and an optional set seen, run the following steps. The result of these steps is a key or invalid, or the steps may throw an exception.

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

  2. If seen contains input, then 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://heycam.github.io/webidl/#dfn-buffer-source-type)
  8. 1. Let bytes be the result of running [get a copy of the bytes held by the buffer source](https://heycam.github.io/webidl/#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) bytes.
  10. If input is an [Array exotic object](https://tc39.github.io/ecma262/#array-exotic-objects)
  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. [Append](https://infra.spec.whatwg.org/#set-append) 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 [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](https://infra.spec.whatwg.org/#list-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.

To convert a value to a multiEntry key with an ECMAScript value input, run the following steps. The result of these steps is a key or invalid, or the steps may throw an exception.

  1. If input is an Array exotic object, 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 list.

    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 convert a value to a key with arguments entry and seen.

        2. If key is not invalid or an abrupt completion, and there is no item in keys equal to key, then append key to keys.

      3. Increase index by 1.

    6. Return a new array key with value set to keys.

  2. Otherwise, return the result of running 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.