proposals icon indicating copy to clipboard operation
proposals copied to clipboard

Private Methods (and accessors) (Stage 3)

Open hzoo opened this issue 8 years ago • 13 comments

Champions: Daniel Ehrenberg @littledan Spec Repo: https://github.com/littledan/proposal-private-methods First presented at the July 2017 meeting: https://github.com/tc39/agendas/blob/master/2017/07.md Moved to Stage 3 at the Sept 2017 meeting: https://docs.google.com/presentation/d/1aI89Jgl7CdtKV6D5-ydieUn_-kgRqAD2X8gGzh62xzc/edit#slide=id.p

Example:

class Counter extends HTMLElement {
  #xValue = 0;

  get #x() { return this.#xValue; }
  set #x(value) {
    this.#xValue = value; 
    window.requestAnimationFrame(
      this.#render.bind(this));
  }

  #clicked() {
    this.#x++;
  }
}

Implementation

  • Initial parser PR (https://github.com/babel/babylon/pull/703) by @Qantas94Heavy

hzoo avatar Jul 28 '17 04:07 hzoo

The main open question here is, should we include private accessors, or only private methods?

cc @diervo

littledan avatar Aug 03 '17 18:08 littledan

We could implement both (parsing wise), and just error in the transform if we only wanted to include one of them? (not sure the context)

hzoo avatar Aug 03 '17 19:08 hzoo

@hzoo Yes, I think that's a good idea. It'd also be pretty natural to start with implementing the syntax for private methods, and then do private accessors as a follow-on.

littledan avatar Aug 03 '17 19:08 littledan

If we ever going to support comma separated fields, we need to do some significant refactor in ClassBody parsing, because we need to create a list of nodes for the multiple decorators.

But I would love to get private fields out of the door first.

diervo avatar Aug 04 '17 00:08 diervo

I was considering taking a crack at this, but I'm having trouble finding any prior art on GitHub or in Slack. Any sense of where the in-progress transform was being worked on? I'm probably slightly out of my depth doing it from scratch but I might be able to help bring something over the finish line.

phyllisstein avatar Jun 17 '18 18:06 phyllisstein

I can't find an in-progress implementation either, but I'm wondering if @rricard @diervo @jridgewell know anything more here or have any particular plans.

littledan avatar Jun 24 '18 13:06 littledan

@tim-mc intended to work on that in relation to https://github.com/babel/babel/issues/8052 and https://github.com/babel/babel/pull/8205

rricard avatar Jun 25 '18 16:06 rricard

Yes, I've started work on the implementation of private methods and am working with a few others (including @littledan, @rricard) on the corresponding 262 test plan.

tim-mc avatar Jun 25 '18 16:06 tim-mc

test262 issue

littledan avatar Jun 25 '18 17:06 littledan

@tim-mc @littledan @rricard Any updates on the progress?

jhpratt avatar Nov 03 '18 21:11 jhpratt

@jhpratt AFAIK, a hard work is in the progress at #8654

Lodin avatar Nov 03 '18 22:11 Lodin

https://github.com/babel/babel/pull/8654 and https://github.com/babel/babel/pull/9101 have added support for private methods and accessors.

tim-mc avatar Jan 22 '19 14:01 tim-mc

almost ready to go 🎉


"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2019-09-06
 *
 * @description auto bind menthods
 * @augments
 * @example
 * @link https://github.com/tc39/proposal-private-methods#Stage-3
 * @link https://babeljs.io/docs/en/babel-plugin-proposal-class-properties
 * @link https://github.com/facebook/create-react-app
 * @link https://create-react-app.dev/docs/adding-typescript
 *
 */

let log = console.log;


import React, { Component } from "react";
import { connect } from "react-redux";

function mapStateToProps(state) {
    return {
        //
    };
}

class ReactComponentAutoBind extends Component {
    constructor(props) {
        super(props);
        state = { count: 0 };
    }
    // es-next class properties
    incCount = () => {
        this.setState(ps => ({ count: ps.count + 1 }));
    }
    render() {
        return (
            <div>
                <p>{this.state.count}</p>
                <button onClick={this.incCount}>add one</button>
            </div>
        );
    }
}

export default connect(
    mapStateToProps,
)(ReactComponentAutoBind);




"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2019-09-06
 *
 * @description private class fields
 * @augments
 * @example
 * @link https://curiosity-driven.org/private-properties-in-javascript
 *
 */

let log = console.log;

// In ESnext, private class fields are defined using a hash # prefix:

class MyClass {
    a = 1;
    // .a is public
    #b = 2;
    // .#b is private
    static #c = 3;
    // .#c is private and static
    static COUNT = 3;
    incB() {
        this.#b++;
    }
}

const m = new MyClass();
m.incB();
// runs OK
m.#b = 0;
// error - private property cannot be modified outside class


"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2019-09-06
 *
 * @description private class methods
 * @augments
 * @example
 * @link https://github.com/tc39/proposal-private-methods
 *
 */

let log = console.log;

class MyClass {
    // private property
    #x = 0;
    // private method (can only be called within the class)
    #incX() {
        this.#x++;
    }
    // private setter (can only be called within the class)
    set #setX(x) {
        this.#x = x;
    }
    // private getter (can only be called within the class)
    get #getX() {
        return this.$x;
    }
}


xgqfrms avatar Sep 06 '19 02:09 xgqfrms