7.1. Extract a key from a value

To extract a key from a value using a key path with value, keyPath and an optional multiEntry flag, run the following steps. 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 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 convert a value to a key with r if the multiEntry flag is false, and the result of running convert a value to a multiEntry key with r otherwise. Rethrow any exceptions.

  4. If key is invalid, return invalid.

  5. Return key.

To evaluate a key path on a value with value and keyPath, run the following steps. 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 of keyPath:

      1. Let key be the result of recursively running 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 of 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).

    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.