Hacker News new | ask | show | jobs
by nosianu 1684 days ago
1) importing module

"require()" can take a non-static string. A variable or a string calculated at runtime.

You can only statically check if that particular feature is not used, but there is no checking the entirety of what require() can be used for/with.

require() is more like dynamic imports in Es modules that are awaited and not like the static ES modules.

2) exporting module

The other issue is on the exporting module's side: You can do strange things with the "exports" object. ES module exporting is more strict to make it guaranteed statically analyzable.

1 comments

Es modules that are awaited and not like the static ES modules.

But this is a non-argument. Awaited or not, you can’t statically check them either. Developers aren’t idiots and they can read “if you pass a string to require/import, tooling can’t figure that out” in a manual.

You can statically check “require(literal)” and cannot “require(variable)”. You can statically check “import from literal” and cannot “import(variable)”.

And awaited imports are essentially just memoize(name => (fs.readFile || fetch)(name).then(wrapAndEval)))(name). It’s not a black magic that is available only to “imports”.

do strange things with the "exports" object

It’s just a value. Somehow analyzers/checkers can work with “var x = do_strange_things()”, but can’t with exports. How is a module boundary different from any other expression boundary?

I really don’t want to think that this is pure zealous smoke blowing, but these arguments are as weak as nil, and leave no options.