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

Getting original constructors without names #15

Open
littledan opened this issue Jul 8, 2018 · 14 comments
Open

Getting original constructors without names #15

littledan opened this issue Jul 8, 2018 · 14 comments

Comments

@littledan
Copy link
Contributor

The JavaScript specification includes a few constructors that aren't properties of the global object, such as %TypedArray% and %GeneratorFunction%. What should be done with these? I see a few options:

  1. Just don't expose them through getOriginalConstructor and expect people to find them another way (this works better for %GeneratorFunction% than %TypedArray%).
  2. Encourage the JS spec to add them as properties of the global object.
  3. Expose them through some other means, for example supporting their spec-internal names, like getOriginalConstructor("%TypedArray%")

I don't have a strong preference between 2 and 3, but 1 would be a little unfortunate.

@domenic
Copy link
Owner

domenic commented Jul 9, 2018

I think from the perspective of the goals of this API, (1) might be OK. So far, none of the nameless original-constructors have been something that we would use when writing a layered API, or indeed that anyone would use when writing JS code. They seem to mostly exist so that there is a coherent prototype chain, with their construction functionality tossed in as an afterthought.

Concretely, we have:

  • Function constructor variants
  • %ThrowTypeError% (not really a constructor)
  • %TypedArray%

%TypedArray% always throws an exception. It's unclear what you could usefully use the original %TypedArray% for.

Dynamically creating functions from strings is similarly fairly niche, and often discouraged.

I'd welcome counterexamples of where these things could be useful. Especially web platform specs that currently build these constructors, and would be impossible to implement in JS without get-originals exposing them.

@jridgewell
Copy link

%PrivateName% (dynamic private fields using weakmap like object) from the decorators proposal isn't (yet, we could change it) exposed on the global.

@domenic
Copy link
Owner

domenic commented Jul 9, 2018

Interesting example. Are there use cases for calling the %PrivateName% constructor? I'm not familiar with how people are expected to write code against private names, but I would assume that if they were meant to be constructed, it would be exposed as a global.

@jridgewell
Copy link

jridgewell commented Jul 9, 2018

Are there use cases for calling the %PrivateName% constructor

Yes. You can see a (large, sorry) write up at tc39/proposal-decorators#68 (comment), or the condensed version below.

I would assume that if they were meant to be constructed, it would be exposed as a global

At the moment, they're passed in as an argument to the decorator call, eg:

function bound(descriptor, PrivateName) {
  // Create some dynamic private here
  const x = new PrivateName('x');

  // Do something with it in class methods, etc.
  // ...
}
class Example {
  @bound x() {}
}

But that makes it a bit odd to use outside of native class decorators, ie for normal objects.

It currently has to be done this way because there's no way to guarantee that PrivateName hasn't been mucked with (and therefore, your dynamic private isn't private at all) without passing in the %PrivateName% to the call. Using get-originals was one option to fix that.

@domenic
Copy link
Owner

domenic commented Jul 9, 2018

Yeah, I think things that are supposed to be used should be exposed globally; half-hearted enforcement of safe meta-programming by having the language pass constructors as arguments to functions seems problematic.

@littledan
Copy link
Contributor Author

It's not an enforcement mechanism, but more like a design finesse. I don't want people to mistakenly think that PrivateName is anything but a decorator metaprogramming construct, so it's exposed specifically to decorators. Of course it's not hard to get at anyway if you want to.

For people who want to call the original methods on PrivateName.prototype, anf guarantee that there won't be interference with monkey-patching, it would be great if this proposal worked for them.

@domenic
Copy link
Owner

domenic commented Jul 9, 2018

Well, are you concerned about constructors, or methods? Both?

@littledan
Copy link
Contributor Author

@domenic In this case, more concerned about their methods.

@domenic
Copy link
Owner

domenic commented Jul 10, 2018

The methods seem like less of an issue; at least in the current form, callOriginalMethod could still work, regardless of the presence or not of a global constructor.

@domenic
Copy link
Owner

domenic commented Aug 8, 2019

With the current draft this is a definite issue, specifically for %TypedArray% methods.

@littledan
Copy link
Contributor Author

littledan commented Sep 3, 2019

Probably more important than %PrivateName% (which is absent from the current decorators draft) is the WeakRef %FinalizationGroupCleanupIteratorPrototype%, where you need to call the next method in order to implement any sort of finalizer. This is present in the Stage 3 draft of WeakRefs, and implemented in V8 behind a flag. I think it's important that built-in module polyfills and WebAssembly be able to register finalizers and use them in a reliable way.

@ljharb
Copy link

ljharb commented Sep 3, 2019

It seems like if a builtin is important/useful enough to warrant direct access via this proposal, that it’s important/useful enough to just be globally reachable? (iow option 2 above)

@littledan
Copy link
Contributor Author

@ljharb From JavaScript, you can get at it by calling the next method directly on the object.

@ljharb
Copy link

ljharb commented Sep 3, 2019

sure, that’s true of all prototype methods, and all properties of builtins including static methods, but this proposal seems to be trying to provide a way to get the functions directly without the intermediate object(s). It just doesn’t seem different to me than, say, array slice.

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

4 participants