7.1. Extract a key from a value

The steps to extract a key from a value using a key path with value, keyPath and an optional multiEntry flag are as follows. The result of these steps is a key, invalid, or failure, or the steps may throw an exception.

  1. Let r be the result of running the steps to evaluate a key path on a value with value and keyPath. Rethrow any exceptions.

  2. If r is failure, return failure.

  3. Let key be the result of running the steps to convert a value to a key with r if the multiEntry flag is unset, and the result of running the steps to convert a value to a multiEntry key with r otherwise. Rethrow any exceptions.

  4. If key is invalid, return invalid.

  5. Return key.

The steps to evaluate a key path on a value with value and keyPath are as follows. The result of these steps is an ECMAScript value or failure, or the steps may throw an exception.

  1. If keyPath is a list of strings, then:

    1. Let result be a new Array object created as if by the expression [].

    2. Let i be 0.

    3. For each item in keyPath:

      1. Let key be the result of recursively running the steps to evaluate a key path on a value using item as keyPath and value as value.

      2. Assert: key is not an abrupt completion.

      3. If key is failure, abort the overall algorithm and return failure.

      4. Let p be ! ToString(i).

      5. Let status be CreateDataProperty(result, p, key).

      6. Assert: status is true.

      7. Increase i by 1.

    4. Return result.

      This will only ever “recurse” one level since key path sequences can’t ever be nested.

  2. If keyPath is the empty string, return value and skip the remaining steps.

  3. Let identifiers be the result of strictly splitting keyPath on U+002E FULL STOP characters (.).

  4. For each identifier in identifiers, jump to the appropriate step below:

    If Type(value) is String, and identifier is “length

    Let value be a Number equal to the number of elements in value.

    If value is an Array and identifier is “length

    Let value be ! ToLength(! Get(value, “length“)).

    If value is a [Blob](https://w3c.github.io/FileAPI/#dfn-Blob) and identifier is “size

    Let value be a Number equal to value’s [size](https://w3c.github.io/FileAPI/#dfn-size).

    If value is a [Blob](https://w3c.github.io/FileAPI/#dfn-Blob) and identifier is “type

    Let value be a String equal to value’s [type](https://w3c.github.io/FileAPI/#dfn-type).

    If value is a [File](https://w3c.github.io/FileAPI/#dfn-file) and identifier is “name

    Let value be a String equal to value’s [name](https://w3c.github.io/FileAPI/#dfn-name).

    If value is a [File](https://w3c.github.io/FileAPI/#dfn-file) and identifier is “lastModified

    Let value be a Number equal to value’s [lastModified](https://w3c.github.io/FileAPI/#dfn-lastModified).

    If value is a [File](https://w3c.github.io/FileAPI/#dfn-file) and identifier is “lastModifiedDate

    Let value be a new Date object with [[DateValue]] internal slot equal to value’s [lastModified](https://w3c.github.io/FileAPI/#dfn-lastModified).

    Otherwise

    1. If Type(value) is not Object, return failure.

    2. Let hop be ! HasOwnProperty(value, identifier).

    3. If hop is false, return failure.

    4. Let value be ! Get(value, identifier).

    5. If value is undefined, return failure.

  1. Assert: value is not an abrupt completion.

  2. Return value.

Assertions can be made in the above steps because this algorithm is only applied to values that are the output of StructuredDeserialize and only access “own” properties.