Ticket #214 (new defect)

Opened 1 year ago

Last modified 1 year ago

(Resolved) Catchall semantics

Reported by: lth Assigned to: lth
Type: defect Priority: trivial
Milestone: Component: Spec
Version: 4 Keywords:
Cc:

Description

The catchall semantics probably need to be cleaned up, they should be simplified s.t. a catchall on an object o is always invoked on access to property p if o.p is not a fixture of o.

We may or may not need [[has]] and [[delete]] catchalls, too -- I think we probably do. Anything else we need?

Attachments

Change History

Changed 1 year ago by lth

Also see #196.

Changed 1 year ago by graydon

Not a fixture of o? That seems a bit much. Can you explain why it's necessary? I thought the idea was for the catchalls to fire any time [[has]] returns false.

Changed 1 year ago by graydon

Sorry, I didn't see the reference to #196. The reasoning there is ... elaborate. I see several good reasons in there for considering a change to these semantics. Haven't a strong opinion on how it's solved. Willing to follow your lead here.

Changed 1 year ago by lth

Discussed at the september f2f. More thought needed.

Changed 1 year ago by lth

Here is the current proposal. In summary, it states that meta::get, meta::set, meta::has, and meta::delete are invoked on an object (if they are defined) if the property being accessed is not defined on the object.

First some observations:

  • Any ReadOnly property is DontDelete (or ReadOnly would mean nothing)
  • Any DontDelete property is a fixture (by #233)
  • A fixture is always defined on the object
  • Ergo no property managed by the catchalls is ReadOnly
  • Ergo there is no need for the ES3 [[CanPut]] machinery in the context of the catchalls

Furthermore,

  • Though only dynamic classes can have new properties, there is no particular reason to outlaw catchalls on non-dynamic classes, since they can implement useful default behaviors. (The predefined classes use this functionality.)

A catchall is invoked when an operation on the object fails to find the property indicated in the operation:

  • meta::get is called when a property is read: obj.x, obj[x], etc; it returns a value
  • meta::set is called when a property is written: obj.x = ..., etc; its return value is discarded (the value of an assignment is always the value of the right-hand side of the assignment)
  • meta::has is called when the language processor invokes [[HasProperty]]
  • meta::delete is called when a property is deleted: delete obj.x
  • The operate-assignment operators, like +=, turn into a get followed by a set
  • The catchalls are invoked before the prototype object is consulted, and it's up to the catchall to ask for default behavior, which depends on the particular catchall.
  • The default behavior is invoked by the catchall throwing the global singleton meta::DefaultAction
  • The default behavior for meta::get and meta::has is to try the prototype object
  • The default behavior for meta::set is to set the value on the dynamic property list of the object, if possible (if the object is not dynamic then this is a run-time error)
  • The default behavior for meta::delete is to delete a local, dynamic property if possible (ditto error)

Finally, we introduce the name private::prototype in classes so that catchalls can inspect their prototype, if necessary (there is no security issue in this).

The property name is the first argument to all four methods, it is an EnumerableId. There is a second argument for meta::set, the value to be set.

If the catchall methods have type annotations, then the first argument must have type EnumerableId, and the return types must be void for meta::set, and boolean for meta::has and meta::delete. The second argument to meta::set and the return type from meta::get can be arbitrary.

The behavior outlined here directly affects #196 and #234.

Changed 1 year ago by lth

Allen notes that explicit invocation of the catchalls may reveal details about how the object is implemented. We could outlaw explicit invocation, but Brendan notes that things like hasOwnProperty already reveals quite a bit, so it's not clear that would buy us much.

Changed 1 year ago by lth

  • owner set to lth
  • component changed from Proposals to Spec
  • summary changed from Catchall semantics to (Resolved) Catchall semantics

Changed 1 year ago by lth

  • priority changed from major to trivial
Note: See TracTickets for help on using tickets.