(Note: you probably shouldn't use this in the real world, but it is totally valid and does exactly what you want.)
Here's an implementation of your print.js
:
function print_things(msg) {
console.log(msg)
}
if(0)typeof await/2//2; export default print_things
<script type=module>
// (renamed to avoid name collision)
import print_things2 from "https://12Me21.github.io/external/print.js"
print_things2("Javascript innovation")
</script>
<script src="https://12Me21.github.io/external/print.js"></script>
<script>
print_things("Hmmmmmmm.")
</script>
This syntax will "hide" the export statement from non-module scripts, because
await/2//2; ...
is parsed differently depending on context:
- In a module or async function:
await
(operator) /2/
(regexp) /
(divide) 2
(number)
- In a normal script:
await
(variable) /
(divide) 2
(number) //2 ...
(comment)
When it's parsed as a comment, the rest of the line is ignored. So, the export
statement is only visible to module scripts.
Here is the relevant part of the specification:
15.8 Async Function Definitions > Syntax > AwaitExpression > Note 1
Compatibility
As a non-module script, it should work in any browser (even ancient versions of Internet Explorer etc.), and is still valid with "use strict"
enabled
However, loading it as a module requires support for "top-level await", which was added a few years after modules themselves (~2021 vs ~2018), so keep that in mind.
(It also works with nodejs, in either mode)
I've used this trick in a library that I wrote, and it's been working fine in multiple environments for several months.
However, it has caused some problems with external tools (frameworks, compilers, minifiers, etc.)