Skip to content

Static Class Features: Stage 3 #8052

@rricard

Description

@rricard

Static Class Features: Stage 3

Advance Static Class Features for Stage 3 (Shu-yu Guo @syg) (Daniel Ehrenberg @littledan)

Proposal co-written with @tim-mc and @robpalme. We also intend to follow up and implement it with @rpamely, @tim-mc, @mkubilayk .

Info

Proposed at TC39 Meeting: May 2018

Slides at the meeting: https://docs.google.com/presentation/d/1YzFr7EIGiX2YagfFMjkI-lVR6ouoRfPbTNLY--NGbC4/edit?usp=sharing

Proposal Repo: https://github.com/tc39/proposal-static-class-features/

Complete article on the subject by Shu-yu Guo: https://rfrn.org/%7Eshu/2018/05/02/the-semantics-of-all-js-class-elements.html

Babel contribution recommended by @jridgewell to @robpalme

The work to be done towards Stage 3 will be added in plugin-proposal-class-properties.

Examples

Static Public Fields

class Account {
  static routingNumber = 1017;
  get transactionIdPrefix() {
    return `${Account.routingNumber}-${this.uuid}`;
  }
}

Static Public Methods

class Account {
  static convertToEuro(dollars) {
     return util.USDToEuro(dollars);
  }

  get euroConversionDisplayAmt () {
    return `Current Balance (EUR): ${Account.convertToEuro(this.accountBalance)}`
  }

Static private fields

class Account {
  static #transactions = [];
  static get nbTransactions() {
    return Account.#transactions.length;
  }
  getDollars() {
    return Account.#transactions.reduce(/* ... */);
  }
}

Static private methods

class Account {
   // ...
  static #makeTransaction(dollars, from, to) {
    Account.#transactions = this.#transactions.concat(/* ... */);
  }
  
  transfer(dollars, targetAccount) {
    return Account.#makeTransaction(dollars, this, targetAccount);
  }
}

Basic Rules

  • Check that the <Class Name>.#<static private field/method> notation is within the lexical scope of <Class Name> - Checked during transform
  • Check that the this.#<static private field/method> has a provenance of <Class Name> - See Subclassing Hazard in the slides (around slide 13) - Checked at runtime

ESTree/Parsing

  • For the static keyword, we use the existing parser
  • For the # character, we use (or enhance) the existing parser (thanks to the work done in Class private properties #7842 - Class private properties)

Transform

Public

  • Public static fields/methods will be added to the <Class Name> object
  • Accessors will be added using Object.assign

Private

  • Transform to use helper functions similar to private instance fields: classStaticPrivateFieldGet and classStaticPrivateFieldSet
  • Add an in-closure _<static private fields/method> variable outside of the class that will be manipulated by the helper functions
  • Here is a potential output of the two last examples put together, in order to explain how to achieve privacy:
var Account =
/*#__PURE__*/
function () {
  "use strict";

  function Account() {}

  babelHelpers.createClass(Account, [{
    key: "transfer",
    value: function transfer(dollars, targetAccount) {
      babelHelpers.classStaticPrivateFieldGet(Account, _makeTransaction)(dollars, targetAccount);
    }
  }, {
    key: "getDollars",
    value: function getDollars() {
      babelHelpers.classStaticPrivateFieldGet(Account, _transactions).reduce(/* ... */);
    }
  }]);
  
  Object.assign(Account, {
    get nbTransactions() {
      return babelHelpers.classStaticPrivateFieldGet(Account, _transactions).length;
    }
  });

  var _makeTransaction = function(dollars, from, to) {
    babelHelpers.classStaticPrivateFieldSet(Account, _transactions, babelHelpers.classStaticPrivateFieldGet(this, _transactions).concat(/* ... */));
  };

  var _transactions = [];

  return Account;
}();

Note that those implementation details are not final but a way to start the conversation and the actual implementation.

cc @jridgewell, @robpalme, @rpamely, @tim-mc, @mkubilayk

Metadata

Metadata

Assignees

Labels

PR: New Feature 🚀A type of pull request used for our changelog categoriesSpec: Class FieldsclaimedoutdatedA closed issue/PR that is archived due to age. Recommended to make a new issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions