Bypassing the constructor of a strong class should be prohibited

59 views
Skip to first unread message

Sébastien Doeraene

unread,
Mar 15, 2015, 5:11:54 PM3/15/15
to streng...@googlegroups.com
Hi,

AFAICT, the proposal does not specify what happens if I try to bypass the constructor of a strong class to create an instance thereof.

Given the class:

"use strong";
class C {
  constructor(x) {
    this.x = x;
  }
}


There are at least two ways to bypass the constructor of a class:

1. Object.create:

"use strong";
const c = Object.create(C.prototype);

or worse, with a property bag:

const c = Object.create(C.prototype, {
  y: {value: "erf"}
});


2. Attach C.prototype as prototype of a weak function:

// weak code
function weakFun(x) {
  this.y = x;
}

"use strong";
const weakFun = somehowGetWeakFun();
weakFun.prototype = C.prototype;
const c = new weakFun(5);

It seems to me that these things should throw some kind of error (TypeError?). Otherwise, all the invariants about strong objects of class C would be broken.

On a related note, what happens if I invoke the constructor() method with an already constructed object:

"use strong";
const c = new C(5);
C.prototype.constructor.call(c, 7);

Likewise, this should probably throw.

A consequence of these restrictions is that it would impossible, even from weak code, to build a "secondary constructor" for a class like this:

"use strong";
class C {
  constructor() {
    this.x = 0; // create the field
  }
  init(x) {
    this.x = x; // but truly initialize it here
  }
}


and then in weak mode:

function D(x) {
  return new C().init(x);
}
D.prototype = C.prototype;

so that I could just call (in weak or strong mode):

const c = new D(5);

Cheers,
Sébastien

Andreas Rossberg

unread,
Mar 17, 2015, 10:03:02 AM3/17/15
to Sébastien Doeraene, streng...@googlegroups.com
On 15 March 2015 at 22:11, Sébastien Doeraene <sjrdo...@gmail.com> wrote:
AFAICT, the proposal does not specify what happens if I try to bypass the constructor of a strong class to create an instance thereof.

Given the class:

"use strong";
class C {
  constructor(x) {
    this.x = x;
  }
}


There are at least two ways to bypass the constructor of a class:

1. Object.create:

"use strong";
const c = Object.create(C.prototype);

or worse, with a property bag:

const c = Object.create(C.prototype, {
  y: {value: "erf"}
});


2. Attach C.prototype as prototype of a weak function:

// weak code
function weakFun(x) {
  this.y = x;
}

"use strong";
const weakFun = somehowGetWeakFun();
weakFun.prototype = C.prototype;
const c = new weakFun(5);

It seems to me that these things should throw some kind of error (TypeError?). Otherwise, all the invariants about strong objects of class C would be broken.

All of these are allowed, but they do not create actual "instances" of C. Thus, invoking C methods on them is supposed to throw.

I recently tried to clarify this in the strawman by avoiding the term "instance", but rather talk about "objects created by the class or subclass". It involves an internal brand check (similar to e.g. to some methods of ES6 promises), not a forgeable instanceof check.
 
 
On a related note, what happens if I invoke the constructor() method with an already constructed object:

"use strong";
const c = new C(5);
C.prototype.constructor.call(c, 7);

Likewise, this should probably throw.

Constructors cannot be called. The above already throws in plain ES6.
 
/Andreas

Sébastien Doeraene

unread,
Mar 17, 2015, 10:38:41 AM3/17/15
to Andreas Rossberg, streng...@googlegroups.com
Hi,

Ah OK, that makes perfect sense. Thanks for the clarifications.

Maybe the strawman could clarify explicitly what you just wrote? From my point of view "objects created by the class or subclass" would have led to the same confusion as "instances". But I'm not familiar with all the details of the ES6 spec, so I might be missing a subtle difference in these two wordings that simply comes from the ES6 spec.

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