`this` inside modules

# Domenic Denicola (11 years ago)

gist.github.com/caridy/eefb9b104874465d4e1c#2-whats-the-execution-context-for-a-module seems to indicate this will become some sort of module meta object with a variety of abilities: this.name, this.address, this.import, this.get, and this.module.

This seems like another unfortunate addition to the WTFJS canon, as it continues to add more confusing meanings for this to the mix.

IMO it would be much better to leave this as undefined, just as it is in strict mode scripts, and thus be able to tell a consistent story that in ES6, this is about methods. The current proposal would instead create a world where this is about methods most of the time, but is a magic ambient variable in some cases (sloppy scripts, modules). This kind of confusion is evident even in the title of that section: it asks "what is the execution context for a module," but it is actually talking about this, which has nothing to do with execution contexts.

If a magically in-scope binding is necessary to access module meta capabilities, giving it a name like module or System.currentModule would be much better.

# Caridy Patino (11 years ago)

Dominic, those are some of the my notes, which by no means cover all the discussion around this topic. @ericf will be posting the full detailed explanation of the stuff we covered.

This is definitely an area that we should continue discussing, especially the API of the "module meta" object, and how to access it from within the module body. I can tell that @wycats and @ericf are opposed to any magic surrounding the module execution (a la nodejs). In the other hand, System.currentModule is probably a bad idea because you don't know which loader was used to load the module (remember that you can use a custom loader for that).

As for the "execution context", the gist mutated multiple times (the original question was about the specs, and the lack of clarity about the evaluation of the module), and we ended up looking into the details of how to access the module meta and loader. Again, this is by no means a doc to reference.

# Anne van Kesteren (11 years ago)

On Mon, Jun 9, 2014 at 6:25 AM, Domenic Denicola <domenic at domenicdenicola.com> wrote:

The current proposal would instead create a world where this is about methods most of the time, but is a magic ambient variable in some cases (sloppy scripts, modules).

This also creates an ever bigger need for an external opt-in flag for modules. E.g. making service workers use strict mode as suggested in slightlyoff/ServiceWorker#294 would no longer allow us to safely upgrade them to module syntax later on. Per www.w3.org/Bugs/Public/show_bug.cgi?id=25868 it is argued that "use modules" would be bad UX, but that seems to be exactly where this is heading, except the syntax is outside of JavaScript.

# Axel Rauschmayer (11 years ago)

I completely agree and was, in fact, going to write my own email on this topic, because I strongly believe we should leave this alone in modules.

Instead, let’s turn “module this” into a module-local special variable with a name such as module, thisModule, currentModule, etc.

# Axel Rauschmayer (11 years ago)

Axel, using module was the first proposal analyzed (3.1 from the gist). I do like it a lot, but other in the meeting opposed to any sort of "automagic" by wrapping the module execution into a function execution with the module argument (a la nodejs),

Overloading this feels even more magic to me and is much less self-descriptive. Apart from the overloading problems (which are significant!), I don’t see that much of a difference between passing in a value for this and setting up a – descriptively named – module-scoped variable.

and the fact that this is not really the module, it is an object that contains, among other things, a reference to another object with the live binding, a relative import, a relative get, etc.

Give it a different name, then. Call it moduleDescriptor, moduleData, etc.

# Erik Arvidsson (11 years ago)

On Mon Jun 09 2014 at 12:25:42 AM, Domenic Denicola < domenic at domenicdenicola.com> wrote:

If a magically in-scope binding is necessary to access module meta capabilities, giving it a name like module or System.currentModule would be much better.

System.currentModule requires magic. It would require the engine to know where the call site was.

We also talked about adding a binding, like NodeJS does but David Herman argued that that is a non starter.

So, if we don't want to use this or introduce a new binding name, or add more magic, the only thing left seems to be new dedicated syntax. In ES4 we this function which is similar to what Axel Rauschmayer suggested.

# Matthew Robb (11 years ago)

What if instead of any sort of magic there was a special relative import a person could specify to get access to the this module?

import module from "@currentModule";
# Kevin Smith (11 years ago)

I agree with Alex completely. Using this as a module meta object is a bad idea. Boo.

# Matthew Robb (11 years ago)

I guess it just seems odd to me that we HAVE a system in place now for importing "stuff" into a Program with an author defined local identifier name and we're discussing magic like using this or module. Just make it another thing the author imports inside their own module? import meta from "./@meta"; or something in the ballpark. Let's use the system we're creating to our advantage.

# Kevin Smith (11 years ago)

(Sorry for the "boo", but I can't mask my disappointment here.)

Erik, was was Dave's argument that a new binding is a non-starter?

# Kevin Smith (11 years ago)

That's true, but I don't understand why we can't just have (to use your example):

import module from "./@meta";

As an implicit import within each module.

# Matthew Robb (11 years ago)

Because that assumes everyone needs it all the time. The nice thing about it being opt-in is that when it comes time to use it a person has to first learn the entry point and from then on be explicit about it. I prefer explicitness 99% of the time because it's easier to track down for new contributors to a code base etc.

# Matthew Robb (11 years ago)

Also, if module were a reserved word and not already used by node.js as an identifier I MIGHT feel differently.

# Kevin Smith (11 years ago)

Because that assumes everyone needs it all the time. The nice thing about it being opt-in is that when it comes time to use it a person has to first learn the entry point and from then on be explicit about it. I prefer explicitness 99% of the time because it's easier to track down for new contributors to a code base etc.

Point taken, and you might be right. But Erik said that Dave said (!) that a binding was a non-starter, and I just don't see that yet.

# Erik Arvidsson (11 years ago)

Also, Yehuda Katz argued that module is a common variable name (QUnit uses it) and reserving it is a non starter.

import {thisModule as yourName} from '@moduleMeta' (bike shedding TBD) is a promising path forward.

# Kevin Smith (11 years ago)

That makes sense - thanks!

# John Barton (11 years ago)

Just another related issue: in Traceur code we use 'this' in modules to mean 'global', because in modules we have no other way to say 'global' in code designed to work in browsers and node.

# Kevin Smith (11 years ago)

Right - I do the same. I think leaving "this" to mean global would be just fine: there's no obvious advantage to changing this aspect of the design, this late in the game. And if there's no obvious advantage, then we're just churning.

# Mark S. Miller (11 years ago)

The genuine global is typically the source of tremendous amounts of authority. Much of the mechanism of SES is built to deny access to the genuine global and to non-whitelisted global variables. Can the module loader API be used to load a module with a different top level binding for "this"?

# Kevin Smith (11 years ago)

IIUC, that use case is provided for with custom module loaders (where you can specify the realm and such).

# Caridy Patino (11 years ago)

another issue with this being global (as it is today by the specs) is the way top level modules will be defined in a page, assuming we will have type="module" for scripts (which is probably were we want to be), what will be the difference between:

<script type="module">
this.foo = 1;
var bar = 2;
import main from "main";
</script>

and

<script>
this.foo = 1;
var bar = 2;
System.import("main");
</script>

it seems to me that the current definition, where this is global, will be an issue when it comes to avoid global variable definition. Ideally, for modules, this.foo and bar will be contained, to have a clear differentiation with the regular script tags.

# John Barton (11 years ago)

On Mon, Jun 9, 2014 at 9:40 AM, Caridy Patino <caridy at gmail.com> wrote:

another issue with this being global (as it is today by the specs) is the way top level modules will be defined in a page, assuming we will have type="module" for scripts (which is probably were we want to be), what will be the difference between:

<script type="module">
this.foo = 1;
var bar = 2;
import main from "main";
</script>

and

<script>
this.foo = 1;
var bar = 2;
System.import("main");
</script>

In the 'module', 'bar' is local and 'main' is imported before the module is evaluated. In 'script' bar is global and the 'main' is imported at the end of the script. The fate of 'this.foo' hangs in the balance until TC39 speaks.

it seems to me that the current definition, where this is global, will be an issue when it comes to avoid global variable definition. Ideally, for modules, this.foo and bar will be contained, to have a clear differentiation with the regular script tags.

My point: if 'this' is not global in modules, then ES6 must have an alternative way to name the global object.

# Andrea Giammarchi (11 years ago)

FWIW, I like the nodejs approach where this is the module itself which as "virtual sandbox" is the only this I'd expect. To reach the global maybe we should think about adding a global indeed while having this undefined would be just making modules not so reusable or portable and would make this meaningless ... which is kinda lame being the most important feature of JS since kinda ever, IMO

# Caridy Patino (11 years ago)

My point: if 'this' is not global in modules, then ES6 must have an alternative way to name the global object.

Yes, we covered that last week. Reflect.global seems like the right place for it considering that it will be defined per realm.

# Marius Gundersen (11 years ago)

What is an arrow function bound to in a module?

export var a = () => this;
# Kevin Smith (11 years ago)

What is an arrow function bound to in a module?

export var a = () => this;

As with all arrow functions, this is lexically bound, so it will bind to whatever this is bound to within the module. Which is kinda the question at hand.

# Andrea Giammarchi (11 years ago)

once again, in node.js this is the exported module. I think we should not make it undefined neither a global pointer ... in node.js this in modules is never global except when you launch the console so only in the main, where we are already consistently good on browsers since this is the global there (script on a page, not modules)

Do we really want to break interoperability with node.js when it comes to this inside modules which is a keyword that could not even be reassigned to nothing and/or monkey patched ?

As tweeted earlier today: I can already smell the next stinking module feature detection if (this) console.log("you are in nodejs") else alert("WTF browser module")

Best

# John Barton (11 years ago)

Was this decision reversed? I don't see Reflect.global in the new spec. online. jjb

# Matthew Robb (11 years ago)

From my interpretation of the last face to face notes and the breakout

session it would appear as if instead you will be able to import mod from this

  • Matthew Robb
# Rick Waldron (11 years ago)

On Thu, Aug 28, 2014 at 2:17 PM, Matthew Robb <matthewwrobb at gmail.com>

wrote:

From my interpretation of the last face to face notes and the breakout session it would appear as if instead you will be able to import mod from this

Can you link to the reference?

# Matthew Robb (11 years ago)

I'm sorry I must have been thinking about something else. This is what I pulled from the last notes:

AWB:

import filename from this;
// which basically: import filename from here;

DD: Like this for relative DH: Completely amenable to this YK:

import * as me from here;
me.import; // `me` is the context object

Conclusion/Resolution

  • the api is right direction
  • each module gets its own version of that object
  • need some sort of access to the module contextual object
  • some sort of declarative form to get at
  • static contextual information about the module
  • Matthew Robb
# Axel Rauschmayer (11 years ago)

The latest info from Domenic is:

import { name, url } from this module;

Source: esdiscuss.org/topic/es6