Skip to content

perl reads a blessed object as a map in typify, clone and validate, where typescript reads a class instance #172

Open

Description

@rjrodger

Where perl differs

typescript's typify answers T_node | T_instance for a class instance, before it considers a map, and the functions built on it follow:

  • clone keeps an instance by reference (its replacer passes T_instance and T_function values through).
  • validate accepts one for $INSTANCE and refuses it for $MAP.
  • select never matches one against a map query.

perl's typify checks ismap first, and ismap accepts any HASH reference, blessed or not (sentinels aside). So a blessed object is T_node | T_map:

  • validate({x => $obj}, {x => '$INSTANCE'}) fails with Expected field x to be instance, but found map, and `$MAP` accepts it.
  • clone($obj) copies it into an unblessed map, keeping any reference back to itself.
  • select([$obj], {...}) matches against the object's own keys.

perl's own maps are tied hashes, which are not blessed, and its sentinels and singletons are excluded before ismap. So a blessed hash here is always a caller's object, and reading it as an instance would cost the port nothing internally.

#171 brings merge into line, because the copying merge from #158 turned this into an out-of-memory failure on objects that refer back to themselves. The rest is left as it is.

Why it was left out of #171

Generated perl SDKs depend on clone unblessing. sdkgen's make_options deep-clones the option tree, and its templates say so and work around it: extend features are rescued raw before the clone, and the secrets feature documents that a custom provider must be a map of callables because a blessed one arrives unblessed, "so the ts contract cannot hold here". Treating a blessed object as an instance would make that contract hold in perl too. It would also change what those SDKs do with blessed options, so it wants its own change, made with sdkgen's perl templates in view.

Shape of a fix

  • typify: a blessed HASH that is not a sentinel answers T_node | T_instance.
  • clone: keep such a value by reference, as typescript does.
  • Then the validate, select and transform paths follow from typify. Pin them with direct tests, since the JSON corpus cannot carry an instance.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions