Re: Outline of exactly how @@create works?

On Aug 7, 2013, at 1:22 PM, Domenic Denicola wrote:

> From: Allen Wirfs-Brock [allen@wirfs-brock.com]
> 
>> Which of these questions are still unanswered by the above doc?
> 
> Wow, it was a good document; I'm sad I forgot about it.
> 
> I think what's still missing would be some guidance, on when it's needed in designing platform classes or user classes, 

First, this is the default way that the new operator works in ES6.  A @@create method is always involved.  Your real question is: When do I need to over-ride the default implementation  of @@create that functions inherit from Function.prototype

The answer is: Anytime you want newing a constructor function to return an exotic object, or if you need to brand its instances, associate private state, or otherwise manipulate the instance before initialization them.

A constructor that returns a proxy is probably the most common example of the exotic object use case:

class MyExotic {
   static [@@create] () {return new Proxy({  }, myHandler)}
   constructor (...args) {
         //initialize this value using args
    }
}

let branded = new WeakSet;
class BrandedMyMe {
   static [@@create] () {
        let obj = super();  //call the default @@create
        branded.add(obj);
        return obj
    }
   constructor (...args) {
         if (!branded.has(this)) throw new TypeError();
         //initialize this value using args
    }
}

class FixedFields {
   static [@@create] () {
        let obj = super();  //call the default @@create
        Object.defineProperty(obj, 'x', {value: 0, writable: true, configurable: false});
        Object.defineProperty(obj, 'y', {value: 0, writable: true, configurable: false});
        return obj
    }
   constructor (x,y) {
         this.x = x;
         this.y = y;
    }
}

>                and why it was used for the new built-ins. (I think this ties in to your caution over in public-script-coord to not use that pattern much.) 

It's use by built-ins so that  the creation of appropriate kinds of exotic objects, branding, and inclusion of private state slots may be inherited by subclasses while still allowing the actual constructor initialization to be over-ridden by the subclass.

The caution is really about avoiding excessive or unnecessary branding. 

> Also, what would the practical consequences of moving everything into @@create be, ignoring the constructor entirely?

constructor arguments are not passed to @@create.  The role of @@create is to physically allocate the right kind of object based upon the internal design of the class.  The role of the constructor is to initialize the newly allocated instances based upon the argument pattern passed to the constructor.  When subclassing you are likely to need to independently inherit or over-ride each capability.  

> 
> One point I was confused on, that re-reading helped me understand, is that @@create actually creates the object instances; it does not manipulate passed-in instances. Thus, getting ahold of e.g. `Date[@@create]` or `HTMLElement[@@create]` would not allow you to do anything special; you could not e.g. turn a normal object into a `Date`. The most you could do is create an "uninitialized" object, and what that means exactly depends it seems on how much stuff you've shifted into @@create vs. the constructor.

exactly, the rough equivalence to remember is:
   new Foo(...args) does the same thing as :  Foo.apply(Foo[@@create](), args)
  
Allen

Received on Wednesday, 7 August 2013 21:41:42 UTC