Skip to content
This repository was archived by the owner on Sep 2, 2023. It is now read-only.
This repository was archived by the owner on Sep 2, 2023. It is now read-only.

Spec: Would !!import.meta ? 'module' : 'not' be a reasonable ask? #395

Open

Description

@SMotaal

I'm think we all must have considered this at some point, but cannot recall.

Q: Is there a safe way for code to test if it is module or not (ie not early/parse error)?

This code would target runtimes supporting import(…) globally, irrespective of semantics, and so my thinking was a clean nice-to-have here could be !!import.meta ? 'module' : 'not' which should not be too much to ask for… thoughts?


Possibly Related Discussions

Activity

  1. added
    brainstormingSafe place to discuss ideas and provide constructive feedback
    on Oct 4, 2019
  2. changed the title [-]Spec: Would `!!import.meta ? 'module' : ` be a reasonable ask?[/-] [+]Spec: Would `!!import.meta ? 'module' : 'not'` be a reasonable ask?[/+] on Oct 4, 2019
  3. ljharb commented on Oct 4, 2019

    @ljharb
    SponsorMember

    If code wants to assert its parse goal, it can do export {} to force ESM or with ({}) {} to force Script.

    You can also wrap either of those in Function and a try/catch to detect it.

  4. SMotaal commented on Oct 4, 2019

    @SMotaal
    Author

    You can also wrap either of those in Function and a try/catch to detect it.

    This one is more on point, but I hit this issue in node:

    // sometimesModule.js — {package: type: 'module'}
    console.log(
      (function() {
        try {
          import.meta.url;
          return 'module';
        } catch (e) {
          return 'not';
        }
      })(),
    );
    > node sometimesModule.js
    
    SyntaxError: Cannot use 'import.meta' outside a module
        at Module._compile (internal/modules/cjs/loader.js:872:18)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:947:10)
        at Module.load (internal/modules/cjs/loader.js:790:32)
        at Function.Module._load (internal/modules/cjs/loader.js:703:12)
        at Function.Module.runMain (internal/modules/cjs/loader.js:999:10)
        at internal/main/run_main_module.js:17:11
    > node --experimental-modules sometimesModule.js
    
    (node:37127) ExperimentalWarning: The ESM module loader is experimental.
    module

    So what I was getting at is sometimesModule.js would be an entrypoint that could be portable everywhere and in case it is node, it will either require or import('module').createRequire(…).

    If code wants to assert its parse goal, it can do export {} to force ESM or with ({}) {} to force Script.

    And so, this is a separate topic, but thanks.

  5. ljharb commented on Oct 4, 2019

    @ljharb
    SponsorMember

    (I crossed out that part of my comment since Function always evaluates as a sloppy Script)

    Why would you want a file to be both Module and Script? Can you help me understand the use case?

  6. bmeck commented on Oct 4, 2019

    @bmeck
    Member

    At the top level this differs between Script and Module.

    // maybe "use strict" here if you wanna have a Strict Script
    let isModule = this === void 0;
    // ... rest of file ...
  7. bmeck commented on Oct 4, 2019

    @bmeck
    Member

    @SMotaal are you still wanting to pursue adding import.meta to Script or is that enough?

  8. SMotaal commented on Oct 4, 2019

    @SMotaal
    Author

    Why would you want a file to be both Module and Script? Can you help me understand the use case?

    @ljharb Not a good way for me to be able to reframe problems (ie can you humor me anyway please), but say this is a workshop for newcomers, where they use the sometimesModule.js to bootstrap.

    I'm inclined to think that for someone less experienced, an intuitive expectation would be to know for certain that they are not in a module.

    As @bmeck points out:

    At the top level this differs between Script and Module.

    And certainly, this is not as intuitive, but also worth being aware of. It still can get messy to explain for such audience, though

    Because there are other ways for such a module to evaluate with this being undefined that can merely be due to a bug in a some loader on some platform:

    const evaluate = (1, eval)(`
      function() {
        "use strict";
        return eval(arguments[0]);
      }
    `);

    It is fair imho to say that semantics of this being undefined and the code being evaluate itself is module or not are rough and hacky to relate to for at least a few folks.

    Therefore: The argument I am trying to consider making is that semantically speaking, import.meta is an object in module, otherwise not — and that could just as well be undefined.


    (I crossed out that part of my comment since Function always evaluates as a sloppy Script)

    Yup, was mid way trying to clean up the code I did towards it and saw it as I replied… thanks though!

  9. ljharb commented on Oct 4, 2019

    @ljharb
    SponsorMember

    It seems to me that newcomers should understand that the two parse goals are different, and which one they’re using, before writing a line of code - just like they’d need to understand which language they’re writing beforehand.

  10. SMotaal commented on Oct 4, 2019

    @SMotaal
    Author

    @ljharb I appreciate there being different views on this, and appreciate others appreciating that when it comes to whohow to go about improving opportunities for newcomers learning, it is fair to assume that there will be different schools of thought, all worth appreciating.

    Fair?

  11. SMotaal commented on Oct 4, 2019

    @SMotaal
    Author

    @SMotaal are you still wanting to pursue adding import.meta to Script or is that enough?

    @bmeck Yes please — sorry, was midway in posting :)

  12. SMotaal commented on Oct 4, 2019

    @SMotaal
    Author

    @ljharb if we just considered how this plays out if it was introduced, where do you see !!import.meta causing runtime ambiguities or concerns?

  13. devsnek commented on Oct 4, 2019

    @devsnek
    Member

    @SMotaal showing people the differences is good, but there's no reason to actually rely on these checks in code. Maybe if you're doing some advanced bundling or something, although even then it's iffy.

    Some web people wanted import.meta in scripts (as an object) and I'm more interested in pursuing that.

  14. 43 remaining items

  15. devsnek commented on Oct 4, 2019

    @devsnek
    Member

    @SMotaal

    pursuing first-class detection by code itself

    Right, but what does that enable us to do? That's the part I'm confused about.

  16. SMotaal commented on Oct 4, 2019

    @SMotaal
    Author

    unreasonable to ask for a new feature because of “possible bugs”
    Top level code already knows the context it’s in via this…

    @ljharb but my point is not about bugs (only the tail I was constructively hoping to be respond to per your request)… or this being the keyword intentionally chosen in the spect to offer the "module" assertions reiterated many times above…

    Just to point out this===undefined only incidentally happens to be fact in "module" being that "module" is always "strict" and this===undefined is actually the reality of "strict" itself.


    but what does that enable us to do

    @devsnek It is about concrete first-class reflection (an expectation that is not at all unreasonable)…


    Sorry, once again, I really need to step away because I feel like my sincere efforts to be constructively working through every scenario posed (with sincere appreciation for them) ends up leaving over-saturating tails that are already addressed in the issue, and cannot be reiterated enough.

  17. ljharb commented on Oct 4, 2019

    @ljharb
    SponsorMember

    You are right that it’s incidental, but it can still be used for this purpose all the same.

  18. devsnek commented on Oct 4, 2019

    @devsnek
    Member

    reflection is good, but it should also be justified.

  19. SMotaal commented on Oct 4, 2019

    @SMotaal
    Author

    reflection is good, but it should also be justified.

    @devsnek I feel a little unsure how all my effort here and your statement can be viewed not with some confusion (I am inclined to trust it is not intended to be offensive, dismissive… etc. not relevant in the context of our forum and mutual collaboration).

  20. devsnek commented on Oct 4, 2019

    @devsnek
    Member

    @SMotaal it is very difficult to solve a problem if you don't know what the problem is. I would love to sit here and brainstorm, it's why I'm subscribed to issues here, but I still have no idea what the problem we're trying to solve is.

  21. SMotaal commented on Oct 29, 2019

    @SMotaal
    Author
  22. targos commented on Oct 29, 2019

    @targos
  23. bmeck commented on Mar 3, 2020

    @bmeck
    Member

    Does this want some kind of change to be requested to the spec?

  24. devsnek commented on Mar 3, 2020

    @devsnek
    Member

    it appears to want import.meta to be valid syntax and return undefined in a script.

  25. SMotaal commented on Mar 4, 2020

    @SMotaal
    Author

    @bmeck I guess the whole point of code deciding to respond to how it is loaded based on import.meta seems fair if import() already accounts to where it is loaded from.

    So, yes, thanks @devsnek, but fair to note undefined here is just meant to stand in for something other than throwing SyntaxError. This would allow code to respond to type in a browser or equivalent. Now import() would likely not be the only way to continue loading its own dependencies, and authors get to decide how they want to do that.

  26. DerekNonGeneric commented on Mar 10, 2020

    @DerekNonGeneric
    Contributor

    FWIW, I've been able to detect the current goal w/o throwing SyntaxError with this one-liner.

    const isModule = typeof module === 'undefined' ? true : false;

    This is because module is not a global furnished in ES module context by any versions of Node.js thus far, while it is always furnished in a CommonJS context.

    @SMotaal, does this solve for you?

  27. ljharb commented on Mar 10, 2020

    @ljharb
    SponsorMember

    global.module = true anywhere in the app would break that code, though.

  28. DerekNonGeneric commented on Mar 10, 2020

    @DerekNonGeneric
    Contributor

    @ljharb, the same would apply for global.import.meta = true.

    Of course, one would need to be careful. This check would need to be performed prior to any instantiation too. So rather than doing the following.

    import module from 'module';

    Prefer:

    import { Module } from 'module';

    Otherwise, it will also result in false-positives.

  29. devsnek commented on Mar 10, 2020

    @devsnek
    Member

    import.meta is not a property lookup, it's a special syntax. you can't override it on global.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions