import.meta and TC39 process as a whole
Jordan Harband
ljharb at gmail.com
Sat Aug 5 21:29:15 UTC 2017
> There’s no code anywhere which doesn’t have an object called Symbol
invoked with `new Symbol()`?
Any such code would either have a local `Symbol`, would have defined a
global `Symbol` that shadowed any pre-defined one (including the new global
in ES6), or would have thrown a ReferenceError or TypeError. Adding
`Symbol` won't break any of that code (because the code that threw was
already broken).
On Sat, Aug 5, 2017 at 2:20 PM, Dmitrii Dimandt <dmitrii at dmitriid.com>
wrote:
> > [Reflect] Not a breaking change because adding a new global isn't new
> syntax, it's just a new variable that exists and essentially can't break
> much.
>
> It either isn’t a breaking change, or can’t break much. It cannot be both.
>
> > Not a breaking change because this constructor did not exist before.
>
> Are you entirely sure? There’s no code anywhere which doesn’t have an
> object called Symbol invoked with `new Symbol()`? The moment you add a
> global anything, you break someone’s code somewhere.
>
> > I don't think I'd call super properties metaproperties for this reason.
> `super` property access is its own class-related syntax that isn't related.
> I do think it sets a perfectly reasonable guideline that makes it clear
> most people have no problem accessing properties off of keywords.
>
> I fail to see where you see guidelines specced out in the specifications
> of metaproperties or superproperties. “Most people” end up just stuck with
> these because they are either unaware that these changes are coming or are
> not active enough to voice their concerns.
>
> > The biggest issue for me in this whole thread is that it's all extremely
> opinion-based. What one person calls complex another would call elegant.
>
> The thing is, I clearly provide arguments in favour of my opinion. Let me
> just summarise them for you.
>
> We now have:
>
> - keywords that are just keywords, really (typeof, case, break, etc.)
> - keywords that are just keywords, but don’t even exist in a language.
> They are reserved for future use in various contexts: always reserved, only
> in strict mode, only in module code etc. (enum, public, private, await
> etc.). May never be used and may possibly be removed, as some keywords have
> been (int, byte, char etc.)
> - literals that are basically keywords (null, true, false)
> - non-keywords that are for all intents and purposes keywords (eval,
> arguments)
> - keywords that look like objects (because they have additional
> properties) which are not objects (new with new.target)
> - keywords that look like functions (because they are invoked like
> functions and return values like functions) which are not functions (import
> and import())
> - keywords that look like objects *and* functions but are neither (import
> and import() and import.meta)
>
> It gets even worse. Because “metaproperties” are not just attached to
> keywords. They are attached to keywords which have *fundamentally different
> semantics* in the language:
> - `new` is an operator[2], it gets `new.target`
> - A function is a callable object [3], and it gets a `function.sent`
> - import is … I don’t know what import is. It gets transformed into a
> separate, made-just-for-import CallExpression and then it gets an
> `import.meta` on top of that (as a hardcoded “metaproperty”).
>
> All of the above are basic facts about the language as it exists now. How
> can adding “properties” to semantically fundamentally different things
> elegant? Or increasing the number of extremely context-dependent things? Or
> overriding existing keywords with new and exceedingly confusing behaviours?
>
> > > So there’s really *nothing* stopping you from designing a proper
> System/Module/Loader/Introspect/Avocado or any subset thereof instead of
> slapping “metaproperties” on everything in sight :)
> >
> > I don't think anyone has claimed that `import.meta` is meant as a
> replacement for these. We still need a loader spec
>
> and a System spec and an Introspect spec, and ... That is why all these
> random additions to vastly different things in the language look like
> ad-hoc shortsighted solutions with no respect for the language or its
> evolution. “We need a thing, we have nowhere to put this thing, let’s add
> this thing to a keyword, because new.target (bad design) has opened a door
> for us”.
>
> > I'd _much_ rather have a static syntactically-defined way to access that
> information over a magically-populated not-quite-global variable like
> `Introspect.context.sent`.
>
> Riiiight. Because import.meta is not a magically-populated
> not-quite-global variable. Oh. Wait. That’s *exactly* what it is.
>
> Even though it’s worse. import is a not-really-a-function-not-
> really-an-object-not-really-a-static-not-really-a-dynamic-keyword which
> is clearly far worse than a properly defined API.
>
>
> On Sat, 05 Aug 2017 at 22:37 Logan Smyth <Logan Smyth
> <Logan+Smyth+%3Cloganfsmyth at gmail.com%3E>> wrote:
>
>> `await` could be added because there is no case in existing code where
>> `await <expression>` would have been valid code, so it is
>> backward-compatible. The same applies for all of the meta-property
>> proposals. The same is not true for `Introspect.context.module`. It's not
>> just a question of it a given construct could be made to behave the way you
>> want, it's also a question of it it would be compatible with existing code.
>>
>> > Introduced in ECMASCRIPT 2015: Reflect is a built-in object that
>> provides methods for interceptable JavaScript operations.
>>
>> Not a breaking change because adding a new global isn't new syntax, it's
>> just a new variable that exists and essentially can't break much.
>>
>> > Introduced in ECMASCRIPT 2015: The Symbol() function returns a value of
>> type symbol, has static properties that expose several members of built-in
>> objects, has static methods that expose the global symbol registry, and
>> resembles a built-in object class but is incomplete as a constructor
>> because it does not support the syntax "new Symbol()”.
>>
>> Not a breaking change because this constructor did not exist before.
>>
>> > ECMAScript 5 introduced: yield, let
>>
>> Not a breaking change because those two can only occur in locations where
>> they can't conflict with existing ES5 code. The extremely limited cases
>> where `let` _could_ be in conflict are explicitly handled in the grammar to
>> prevent breaking changes.
>>
>> > ECMASCRIPT 6 introduced: await as a reserved word in module code
>>
>> Same as above.
>>
>> > So, introducting new things into the language is not really such a big
>> problem as it’s made out to be ;)
>>
>> No-one said introducing things was not possible, but we can't break
>> existing code.
>>
>> > Don’t forget that `super` gets its own properties. Since there’s no
>> specification of what “metaproperties” are, they are just called
>> superproperties[7] in the grammar. Because reasons.
>>
>> I don't think I'd call super properties metaproperties for this reason.
>> `super` property access is its own class-related syntax that isn't related. I
>> do think it sets a perfectly reasonable guideline that makes it clear most
>> people have no problem accessing properties off of keywords.
>>
>> > The problem with “metaproperties” is that they make the language more
>> complex, chaotic and make it difficult to reason about the language.
>>
>> This seems to be the core of your argument, but I honestly don't quite
>> see why it is more complex/chaotic. The biggest issue for me in this whole
>> thread is that it's all extremely opinion-based. What one person calls
>> complex another would call elegant.
>>
>> What specifically is difficult to reason about that wasn't already
>> complex? Same for `function.arguments`. You're saying you think it's better
>> to have an automatically-created `arguments` variable in every single
>> function instead of having syntax to access it? `arguments` and `this` as
>> two auto-initialized bindings are some of the most confusing parts of JS.
>>
>>
>> > So there’s really *nothing* stopping you from designing a proper
>> System/Module/Loader/Introspect/Avocado or any subset thereof instead of
>> slapping “metaproperties” on everything in sight :)
>>
>> I don't think anyone has claimed that `import.meta` is meant as a
>> replacement for these. We still need a loader spec, but having a syntactic
>> way to access data about the current active module is absolutely a useful
>> thing to have. It's no different than CommonJS's __dirname and __filename
>> among others. The logic for implementing a loader is separate from the
>> logic for defining the behavior of module execution itself.
>>
>> I'd _much_ rather have a static syntactically-defined way to access that
>> information over a magically-populated not-quite-global variable like `Introspect.context.sent`.
>> In a perfect world absolutely `module` could have been a keyword, but at
>> this point making that change seems like an absolute no-go because it could
>> easily break existing code.
>>
>> > Like look. function.sent?? Really? And it’s extremely highly
>> context-specific: “function.sent can appear anywhere a YieldExpress would
>> be legal. Referencing function.sent outside of a GeneratorBody is a Syntax
>> Error.”
>>
>> It's the exact same context-specific behavior as `yield` and they are
>> both tied to generator functions. How is that in any way unexpected?
>>
>>
>> On Sat, Aug 5, 2017 at 12:43 PM, Dmitrii Dimandt <dmitrii at dmitriid.com>
>> wrote:
>>
>>> I just realised that there is also the argument that “global object
>>> cannot get current context” and other limitations applied to whether a
>>> theoretical “System/Module/Loader/Introspect” would be a global module,
>>> or object, or keyword, or any (potentially context-sensitive) combination
>>> of these.
>>>
>>> However, this all basically depends on what you specify in the standard,
>>> doesn’t it? :)
>>>
>>> - Dynamic import has a “forbidden extensions” section[1] and how it
>>> should work when it’s invoked as a CallExpression [2]
>>> - import.meta has a full section describing how the runtime should
>>> behave when encountering this particular property[3]
>>> - new global objects like Reflect, Proxy, Symbol have specifications on
>>> what they are and hoe they should be treated [4]
>>>
>>> A theoretical global object/keyword/identifier/special form X could be
>>> specified as <object/keyword/identifier/avocado>. X.someProperty: when
>>> encountered, let context be Ctx, let A be B, and C be B, populate with
>>> properties from here and there and everywhere.
>>>
>>> Or look at the AwaitExpression[5]. There are specific limits in place to
>>> guard where and how it’s used and when it is to be evaluated as
>>> AwaitExpression.
>>>
>>> So there’s really *nothing* stopping you from designing a proper
>>> System/Module/Loader/Introspect/Avocado or any subset thereof instead
>>> of slapping “metaproperties” on everything in sight :)
>>>
>>> Like look. function.sent?? Really? And it’s extremely highly
>>> context-specific: “function.sent can appear anywhere a YieldExpress would
>>> be legal. Referencing function.sent outside of a GeneratorBody is a Syntax
>>> Error.” [6]
>>>
>>> Look. Here’s a proposal: `Introspect.context.sent can appear anywhere a
>>> YieldExpress would be legal. Referencing Introspect.context.sent outside of
>>> a GeneratorBody is a Syntax Error.` And then you can use
>>> `Introspect.context.target` instead of `new.target`.
>>> `Introspect.context.module` instead of `import.meta`. Clean. Reasonable.
>>> Extensible. Future-proof.
>>>
>>> [1] https://tc39.github.io/proposal-dynamic-import/#sec-forb
>>> idden-extensions
>>> [2] https://tc39.github.io/proposal-dynamic-import/#sec-import-calls
>>> [3] https://tc39.github.io/proposal-import-meta/#sec-source-
>>> text-module-records
>>> [4] https://tc39.github.io/ecma262/#sec-reflection, https://
>>> tc39.github.io/ecma262/#sec-proxy-objects, https://tc39.
>>> github.io/ecma262/#sec-symbol-objects
>>> [5] https://tc39.github.io/ecma262/#prod-AwaitExpression
>>> [6] https://github.com/allenwb/ESideas/blob/master/Generator
>>> %20metaproperty.md
>>>
>>>
>>>
>>> On Sat, 05 Aug 2017 at 20:40 dmitrii at dmitriid.com <dmitrii at dmitriid.com>
>>> wrote:
>>>
>>>> The problem with “metaproperties” is that they make the language more
>>>> complex, chaotic and make it difficult to reason about the language.
>>>>
>>>> See my previous post about the multitude of keyword and keyword-like
>>>> types that the language has. It’s so bad that even “metaproperty” concept
>>>> itself isn’t defined in the standard except as a hardcoded `new.target` [1]
>>>>
>>>> If you read, for example, through the import.meta draft, you see things
>>>> ripe for inclusion in a proper API object.
>>>>
>>>> It gets even worse. Because “metaproperties” are not just attached to
>>>> keywords. They are attached to keywords which have *fundamentally different
>>>> semantics* in the language: `new` is an operator[2], it gets `new.target`.
>>>> A function is a callable object [3], and it gets a `function.sent`. Import
>>>> is … I don’t know what import is [4]. It gets transformed into a separate,
>>>> made-just-for-import CallExpression[5] and then it gets an `import.meta`
>>>> on top of that [6] (as a hardcoded “metaproperty").
>>>>
>>>> Don’t forget that `super` gets its own properties. Since there’s no
>>>> specification of what “metaproperties” are, they are just called
>>>> superproperties[7] in the grammar. Because reasons.
>>>>
>>>> All this is chaos from the perspective of developer experience. And
>>>> truly looks like random ad-hoc solutions to immediate problems with no
>>>> long-term goals. Imagine how much better *and* future-proof it would be if
>>>> all this was in the form of a unified centralised API? There is a reason
>>>> people laugh at PHP for its API and language design.
>>>>
>>>> [1] https://www.ecma-international.org/ecma-262/#sec-meta-properties
>>>> [2] https://www.ecma-international.org/ecma-262/7.0/#sec-new-operator
>>>> [3] https://www.ecma-international.org/ecma-262/7.0/#sec-
>>>> terms-and-definitions-function
>>>> [4] https://www.ecma-international.org/ecma-262/7.0/#sec-imports
>>>> [5] https://tc39.github.io/proposal-dynamic-import/#sec-left
>>>> -hand-side-expressions
>>>> [6] https://tc39.github.io/proposal-import-meta/#sec-left-
>>>> hand-side-expressions
>>>> [7] https://www.ecma-international.org/ecma-262/7.0/#sec-
>>>> left-hand-side-expressions
>>>>
>>>>
>>>> On Sat, 05 Aug 2017 at 18:59 Matthew Robb <Matthew Robb
>>>> <Matthew+Robb+%3Cmatthewwrobb at gmail.com%3E>> wrote:
>>>>
>>>>> I really can't find a good resource on direct vs indirect evaluation
>>>>> but my understanding is it's one of the main considerations for using a
>>>>> keyword over an identifier for contextual information. One example which is
>>>>> already in the language would be 'eval' which you can read a little about
>>>>> here: http://2ality.com/2014/01/eval.html
>>>>>
>>>>> Now you might be able to have an API that gets you the same result as
>>>>> the context sensitive keywords but it would be less ergonomic among other
>>>>> things: Reflect.getModuleMetaProperty(someModuleNs, 'propName') but
>>>>> this becomes much more difficult to do FROM WITHIN THE MODULE ITSELF.
>>>>> Anything that is, let's call it tangible, cannot receive implicit
>>>>> contextual information it must have something passed to it that it would
>>>>> use to look up said information.
>>>>>
>>>>> Sure there could be arguments made about introducing new environment
>>>>> type records to the top level module scope of all modules but this is
>>>>> potentially much more error prone and likely to lead to more and bigger
>>>>> questions down the road. 'module' in particular is a really bad choice imo
>>>>> as node/commonjs have already introduced a 'module' identifier into all of
>>>>> their module scopes hence `module.exports = ...`. There may be solutions to
>>>>> working around that in one form or another BUT the 'trend' in TC39 to use
>>>>> keyword meta properties for context sensitive information is to avoid
>>>>> solving ever edge case of conflict that would impact existing code and
>>>>> users. It really is a fairly ripe space for powerful and ergonomic features
>>>>> like `super` which feel like "magic". The same is true for import.meta but
>>>>> it may be harder to identify right off as the uses haven't all been fully
>>>>> introduced such as environment specific properties and potentialy other
>>>>> loader hooks.
>>>>>
>>>>> NOW as I was writing this it came to mind that we DO have a new
>>>>> syntactic form for private data coming in the form of private fields which
>>>>> use a hash prefix. It would be interesting to explore using the same syntax
>>>>> for module scoped private fields:
>>>>>
>>>>> ```js
>>>>>
>>>>> console.log(#dirname);
>>>>> ```
>>>>>
>>>>>
>>>>> - Matthew Robb
>>>>>
>>>>> On Sat, Aug 5, 2017 at 12:35 PM, Dmitrii Dimandt <dmitrii at dmitriid.com
>>>>> > wrote:
>>>>>
>>>>>> Too bad emails don’t have "thumbs up" and “+1”s :) So here’s my "+1”
>>>>>> to you
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Sat, 05 Aug 2017 at 18:28 "T.J. Crowder" <">"T.J. Crowder" >
>>>>>> wrote:
>>>>>>
>>>>>>> On Sat, Aug 5, 2017 at 5:05 PM, Dmitrii Dimandt
>>>>>>> <dmitrii at dmitriid.com> wrote:
>>>>>>> > So, in my opinion, the argument for not adding new global entities
>>>>>>> > such as System, or Module, or Loader (or heck, even all three of
>>>>>>> > them) being “these are not keywords, we can’t introduce them” is
>>>>>>> > really really weak.
>>>>>>>
>>>>>>
>>>>>> Is anyone making that argument? I certainly am not. Not only is it
>>>>>> possible to add more global entities, as you point out, it's been done
>>>>>> repeatedly: `Symbol`, `Reflect`, etc. They just can't be *keywords* without
>>>>>> breaking things. They have to be identifiers. Which means they have
>>>>>> bindings with values. Which means those values can be copied. Which has
>>>>>> implications.
>>>>>>
>>>>>> On Sat, Aug 5, 2017 at 5:08 PM, Dmitrii Dimandt
>>>>>> <dmitrii at dmitriid.com> wrote:
>>>>>> >
>>>>>> > That’s not what I was really aiming at :)
>>>>>> >
>>>>>> > The original concern was “to get ‘module’ : 1. It's a
>>>>>> > context-sensitive keyword, and code that's using it needs to
>>>>>> > be updated when migrated to a module. “
>>>>>> >
>>>>>> > I was just pointing out that ‘import’ is already a context-
>>>>>> > sensitive keyword (as are a bunch of others, like super.
>>>>>> > Is super a keyword BTW?)
>>>>>>
>>>>>> My point was that this would be the only case I know of where it
>>>>>> would be a keyword in one context but an identifier in another in the
>>>>>> *exact same production*. `super`, `import`, etc., are **always** keywords.
>>>>>> You just can't use them except in certain contexts. So I shouldn't have
>>>>>> said "context-sensitive keyword" so much as "keyword or identifier
>>>>>> depending on context." (But then...I did, earlier; I figured the shorthand
>>>>>> was okay after spelling it out longhand. :-) )
>>>>>>
>>>>>> But again: Maybe that's feasible. Or maybe it's not a problem passing
>>>>>> the value around, in which case a predefined `module` identifier only in
>>>>>> module code isn't a problem anyway.
>>>>>>
>>>>>> -- T.J. Crowder
>>>>>>
>>>>>>
>>>>
>>>
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170805/14c8754d/attachment-0001.html>
More information about the es-discuss
mailing list