Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: abstract-refs based private methods in class literal #12

Closed
zloirock opened this issue Feb 27, 2015 · 9 comments
Closed

Proposal: abstract-refs based private methods in class literal #12

zloirock opened this issue Feb 27, 2015 · 9 comments

Comments

@zloirock
Copy link

This repo except abstract references proposal contains note about private keyword. November tc39 meeting contain discuss about private properties in class literal. Abstract references gives sugar for virtual methods call, but it's too bulky for private methods:

var C = (() => {
  private X, Y;
  function privateMethod(y){
    console.log(this::X + y);
  }
  return class {
    constructor(x, y){
      this::X = x;
      this::Y = y;
    }
    publicMethod(){
      this::privateMethod(this::Y);
    }
  }
})();

new C(27, 15).publicMethod(); // => 42

I propose add private keyword for methods in class literal as sugar for it:

class C {
  private X, Y;
  constructor(x, y){
    this::X = x;
    this::Y = y;
  }
  private privateMethod(y){
    console.log(this::X + y);
  }
  publicMethod(){
    this::privateMethod(this::Y);
  }
}

new C(27, 15).publicMethod(); // => 42
@zenparsing
Copy link
Owner

Hi @zloirock!

Thanks for the feedback. Based on discussions here and at the Nov TC39 meeting we've moved away from the "abstract references" design. It has now been split up into a function bind operator proposal and a private fields proposal:

Please check those out and let me know what you think.

@zloirock
Copy link
Author

@zenparsing wow... Method extraction syntax really lacked in abstract refs proposal. Not sure about those conception private fields - unusual. But i don't see anything about right-to-left syntax modifiable in userland. I hope that the move away of these parts of abstract-refs does not buries something like Symbol.referenceGet? I actively use it in my projects.

@zenparsing
Copy link
Owner

@zloirock Interesting. Would you mind talking about how you use Symbol.referenceGet, apart from function bind, or weakmaps?

@zloirock
Copy link
Author

@zenparsing basical, demo:

let {map} = Dict;

// static version:
var O = map({q: 1, w: 2, e:3}, it => it * it);
log(O); // => {"q":1,"w":4,"e":9}

// method version, redefined @@referenceGet:
var O = ({q: 1, w: 2, e:3})::map(it => it * it);
log(O); // => {"q":1,"w":4,"e":9}

// virtual accessors:
let size = {
  [Symbol.referenceGet](it){
    return Object.keys(it).length;
  },
  [Symbol.referenceSet](it, length){
    for(let key of Object.keys(it).slice(length))delete it[key];
  }
}

log({q: 1, w: 2, e: 3}::size); // => 3
let dict = {q: 1, w: 2, e: 3};
dict::size = 2;
log(dict); // => {q: 1, w: 2};

@zenparsing
Copy link
Owner

@zloirock Cool! We couldn't really think of a use case for virtual accessors, but this seems plausible.

Still, one of the main objections to referenceGet/Set was that it was serving widely divergent use-cases with the same operator, and hence would be confusing to users. What do you think of that argument?

@zloirock
Copy link
Author

@zenparsing

Still, one of the main objections to referenceGet/Set was that it was serving widely divergent use-cases with the same operator, and hence would be confusing to users.

I wanted to write it after this your comment, but forgot :) I think, abstract-references conception should be maintained fully, maybe with changed syntax.

@zloirock
Copy link
Author

@zenparsing Private fields proposal looks not very user-friendly. Abstract references and sugar from this thread do the same and some more :) But syntax really should differ from method extraction.

@zenparsing
Copy link
Owner

@zloirock There were a couple of usability issues with abstract references + weakmaps:

First, accidental shadowing of the field name:

class Point {
    private x, y;
    constructor(x, y) {
        // Oops - parameter "x" is shadowing the private field name
        this::x = x;
        this::y = y;
    }
}

I think users coming from other OOP languages would be tripped up by this.

Second, WeakMap's Symbol.referenceSet is susceptible to confused deputy attacks, where code is tricked into setting a private field on an imposter object, which can potentially open up further attacks:

class C {
    private x;
    constructor() { this::x = 0 }
    mutateX(value) { this::x = value }
}
let imposter = {};
C.prototype.mutateX.call(imposter, 123);
// imposter now has a private field that it shouldn't

The private fields proposal fixes both of these issues. If you can spot specific usability problems with private fields, though, please add them as issues to that repo. Feedback is much appreciated! : )

@zloirock
Copy link
Author

@zenparsing I did not say anything about WeakMap, private keyword can define PrivateMap with non-writable non-configurable methods and, possible, accepting only one class instances :) About field name - @ can cause not fewer errors. Also, possible compile time error if declared variable with name equals private field name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants