Cloning a strong object in strong mode

39 views
Skip to first unread message

Sébastien Doeraene

unread,
Mar 15, 2015, 11:35:01 AM3/15/15
to streng...@googlegroups.com
Hello,

I'm looking into cloning a strong object, in strong mode, with the following assumptions about the constructor() of the class and all its parents:
* It does not take any parameter, and
* It only calls super() and creates the fields with literals as initial values (so there's no side-effect)

The clone should be shallow, i.e., all the fields of the new object should be === to the corresponding fields of the original object. The new object should be a proper instance of the same class as the original object. It should therefore have the same prototype, and be strong.

I've come up with this, which works in the current d8:

function clone(o) {
  const constructor = Object.getPrototypeOf(o).constructor;
  const r = new constructor();
  for (const p of Object.keys(o))
    r[p] = o[p];
  return r;
}


Does it work only "by chance" (since not all of the strong mode spec is implemented yet), or is it guaranteed to work under strong mode?
I'm pretty sure it's well specified to work---especially for a strong class, since it's guaranteed, I believe, that the `constructor` field of the prototype cannot be changed, and will always truly be the constructor---but I'd like to ask for a confirmation here.

Cheers,
Sébastien

Dimitris Vardoulakis

unread,
Mar 16, 2015, 11:24:58 AM3/16/15
to streng...@googlegroups.com


On Sunday, March 15, 2015 at 8:35:01 AM UTC-7, Sébastien Doeraene wrote:
Hello,

I'm looking into cloning a strong object, in strong mode, with the following assumptions about the constructor() of the class and all its parents:
* It does not take any parameter, and
* It only calls super() and creates the fields with literals as initial values (so there's no side-effect)

The clone should be shallow, i.e., all the fields of the new object should be === to the corresponding fields of the original object. The new object should be a proper instance of the same class as the original object. It should therefore have the same prototype, and be strong.

I've come up with this, which works in the current d8:

function clone(o) {
  const constructor = Object.getPrototypeOf(o).constructor;
  const r = new constructor();
  for (const p of Object.keys(o))
    r[p] = o[p];
  return r;
}

You can't do that in strong mode. Instances are sealed, so all properties are added in the constructor, and you can't create new properties by assignment.

Dimitris Vardoulakis

unread,
Mar 16, 2015, 11:26:47 AM3/16/15
to streng...@googlegroups.com
There are no slide numbers in this presentation, but see the slides titled Sane Objects and Sane Classes.

Sébastien Doeraene

unread,
Mar 16, 2015, 11:52:31 AM3/16/15
to Dimitris Vardoulakis, streng...@googlegroups.com
Hi,

I am well aware that strong objects are sealed. But note that the properties will already have been created by the call to `new constructor()`. Since `o` itself is a strong object, we know that its constructor creates all the properties that it has, so iterating these properties is exactly the same as iterating over the properties created on `r` by `new constructor()`. So these assignments do not create new properties, they just modify already existing properties of `r`.

Cheers,
Sébastien

--
You received this message because you are subscribed to the Google Groups "Strengthen JS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to strengthen-j...@googlegroups.com.
To post to this group, send email to streng...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/strengthen-js/87facc53-3c48-4ce7-969f-98093afc862d%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Andreas Rossberg

unread,
Mar 17, 2015, 9:54:32 AM3/17/15
to Sébastien Doeraene, Dimitris Vardoulakis, streng...@googlegroups.com
I think this should currently work, but it is probably not future-proof. It will no longer fly if we ever add either constant or private attributes to classes (e.g. we hope to get both in SoundScript eventually).

In general, external cloning of objects can never work correctly, in any language with a sufficiently interesting object model. May I ask why you need it?

/Andreas


Sébastien Doeraene

unread,
Mar 17, 2015, 10:32:25 AM3/17/15
to Andreas Rossberg, Dimitris Vardoulakis, streng...@googlegroups.com
Hi,

Ah, I did not foresee stuff that far. I only looked at the current spec. But if it's fine in Strong Mode, as currently specified, I'll keep it that way for now. I'll figure something out when the time comes, when moving to SoundScript.

I need this basically to implement java.lang.Object.clone() in Scala.js. The good thing is that I know that `o`, the object to clone, is an instance of a Scala.js-generated class, so I know a few things about it, in particular, I know that its constructor() only creates the fields, and does nothing else.

I guess, even if SoundScript supported constant and private attributes, Scala.js wouldn't emit those. Constants doesn't really work when you need overloaded constructors, which need to be implemented as several "init" methods. And private fields would hinder a lot of the optimizations that Scala.js does before emitting JavaScript.
So maybe I'm fine with the not-future proof aspect, at least for now. Worst comes to worst, I would add an additional "init" overload to all classes to create-clone from another object.

Thanks for your response.

Cheers,
Sébastien
Reply all
Reply to author
Forward
0 new messages