tc39 / proposal-function-implementation-hiding

JavaScript language proposal: function implementation hiding
https://ci.tc39.es/preview/tc39/ecma262/pull/1739
MIT License
102 stars 7 forks source link

Class-body directive prologue is incompatible with class fields #21

Closed domenic closed 5 years ago

domenic commented 5 years ago

Discovered in TC39 today.

class Foo {
  "hide implementation";

   constructor() { }
   bar() { }
}

declares a public field named "hide implementation". Whee!

Solutions

Omit directive prologue in class bodies

We could just omit this capability. Then developers would have several more-awkward options, such as:

"hide implementation";

class Foo {
   constructor() { }
   bar() { }
}

// Anything else in the source file also gets implementation-hidden, which might be bad.

or

let Foo = (() => {
  "hide implementation";
  return class Foo {
     constructor() { }
     bar() { }
  };
})();

or

class Foo {
   constructor() {
     "hide implementation";
   }
   bar() {
     "hide implementation";
   }

   // repeat as needed
}

Don't use directive prologues

Basically #13.

Something else clever

TBD.

ljharb commented 5 years ago
class Foo ("hide implementation", "future pragma maybe?") {
}
class Foo extends Bar ("hide implementation") {
}
nicolo-ribaudo commented 5 years ago
class Foo extends Bar ("hide implementation") {
}

That is a function call

ljharb commented 5 years ago

lol oops, not so clever after all

domenic commented 5 years ago

In particular, if we're going to add any new syntax, I think it should be either:

ljharb commented 5 years ago

" Anything else in the source file" in the OP implies something that's not clear to me; do you mean, hides anything else in the function the class is contained in?

domenic commented 5 years ago

do you mean, hides anything else in the function the class is contained in?

Yes, although in that example there was no wrapping function, so it's the whole source file.

ljharb commented 5 years ago

ah, so stack traces from the entire module would be suppressed then? i'll hide these as off topic (unhide as you like) but that seems worth a stronger callout (that it's not just about functions)

rbuckton commented 5 years ago

What about a different prologue for hiding class implementations, specified in the constructor:

class Foo {
  constructor() {
    "hide class implementation";
  }
}
ljharb commented 5 years ago

I like that - considering the constructor function is what class actually produces, this seems like a neat solution to the problem (and answers the question of what would happen if i put the pragma in the constructor with the current proposal)

rbuckton commented 5 years ago

I would imagine "hide implementation"; in the constructor would only hide the body of the constructor itself, while "hide class implementation"; would hide the body of the entire class.

ljharb commented 5 years ago

Although now that i think about it, it’d be weird if the constructor pragma impacted static methods :-/

michaelficarra commented 5 years ago

@rbuckton The constructor does not always appear first (or even early) in the class body. I wouldn't want to be unable to tell that we're in a special kind of context until the whole class body is read.

rbuckton commented 5 years ago

@ljharb: Possibly sounds like https://github.com/tc39/proposal-class-static-block#readme could be an option:

class Foo {
  static {
    "hide implementation";
  }
}

@michaelficarra: True, but there's still value in the simple solution.

rbuckton commented 5 years ago

Another option could be this:

class Foo {
  ("hide implementation");
}

This keeps the pragma at the top of the class and doesn't conflict with public fields, for the added cost of two characters.

michaelficarra commented 5 years ago

We're no longer interested in adding new directive placements.

ljharb commented 5 years ago

@michaelficarra so what's the plan for hiding the implementation of the constructor/class body? a pragma inside the constructor?

michaelficarra commented 5 years ago

@ljharb If you want to affect only the constructor, put it in the constructor. If you want it to apply to all of the methods of the class, wrap the class in an IIFE or just put the directive in the enclosing scope if you don't mind the over-application.

ljharb commented 5 years ago

Gotcha - i ask because the constructor’s implementation is the entire class body, so hiding it is hiding the class (altho not necessarily all its methods)