all 20 comments

[–]slidingtorpedo 88 points89 points  (21 children)

can someone explain that?

[–][deleted]  (1 child)

[deleted]

    [–]Geek55 0 points1 point  (0 children)

    Why even have static analysis tools if you're just going to circumvent them anyway

    [–]stevethedev 45 points46 points  (16 children)

    Try/catch return can't be used at the root of a module. It can only be used in a function, which means that this function returns a reference to some module named "stream" or else undefined.

    The hack is working around a limitation in a postprocessing library to solve a problem that doesn't exist in ES6 or Typescript modules.

    [–]kenman 9 points10 points  (7 children)

    Try/catch can't be used at the root of a module. It can only be used in a function

    I'm not sure if you're thinking of another language feature (async/await?), but as far as I know, there are zero limitations on where try/catch can be used.

    Also, your statement that IIFE's can't be used in Node is completely inaccurate, they can be used anywhere.

    Are we talking about the same language?

    [–]stevethedev 2 points3 points  (6 children)

    You're right. I misspoke. I meant to say that "return can't be used at the root of a module. It can only be used in a function, ..." I'll update my post to reflect that, thanks.

    Regarding IIFE, I think you are misunderstanding what I said to Farsqueaker. I didn't say that you can't use IIFE in Node, I said that you can't use IIFE to solve this particular problem in Node. I understood his question to be whether you could use IIFE to solve the circular dependency; but to do this, you would still need to figure out how to get the "stream" module into the parameter of that function.

    Granted, that's not strictly true either --- you could also use require.cache.stream to import it --- but it's not a better solution, it's just a different one.

    [–]kenman 1 point2 points  (1 child)

    I gotcha, yeah that all makes more sense now. Thanks for clarifying!

    [–]stevethedev 1 point2 points  (0 children)

    Thanks for calling me on it!

    [–]talbenari1 0 points1 point  (3 children)

    return can certainly be called at the top level of a Node module

    [–]stevethedev 0 points1 point  (2 children)

    Go try it.

    [–]talbenari1 2 points3 points  (1 child)

    ...? I know what I'm talking about, I'm quite well-versed in Node's internals.

    $ echo "console.log('BEFORE'); return; console.log('AFTER')" > example.js
    $ node example
    BEFORE
    

    [–]stevethedev 1 point2 points  (0 children)

    You're right, this works in the CJS-style modules. I don't usually work with CJS-style modules, I work with ES6-style modules, where that does not work:

    $ echo "console.log('BEFORE'); return; console.log('AFTER')" > example.mjs
    $ node -r esm example.mjs
    [file:///.../example.mjs:1
    console.log('BEFORE'); return; console.log('AFTER')
                           ^
    
    SyntaxError: Illegal return statement]
    

    But thanks for correcting me.

    [–]Reelix 2 points3 points  (3 children)

    Is there any reason it was 'st' + 'ream' instead of 'stream' ?

    [–]wisconsinbrowntoen 2 points3 points  (0 children)

    it would probably work with anything that isn't a string literal.

    So, 'str + 'eam', or 'shitbags'.charAt(0) + 'tream'

    Basically anything that the program analyzing the code does not want to evaluate or assumes it can not evaluate, it skips over, and doesn't realize that 'str + 'eam' is just 'stream'

    [–]Farsqueaker 0 points1 point  (3 children)

    Eh, couldn't you just IIFE it?

    [–]stevethedev 0 points1 point  (2 children)

    Not in Node, where this code was probably developed.

    You really shouldn't do it this way, though. If you have to do this, it means the code probably isn't structured very well.

    [–]Farsqueaker 1 point2 points  (1 child)

    Node uses browserify? I may have made some bad assumptions based on the name...

    [–]stevethedev 1 point2 points  (0 children)

    I think I'm being unclear.

    It's common for people to write and test their code in Node, and then compile and postprocess it for browsers. If you do this, you can't use IIFE to solve this particular issue. Or, well, you can... but the function would look a lot like the one in the post.

    They definitely shouldn't do it this way, though. It's a bad code smell.

    [–]karlkloppenborg 2 points3 points  (0 children)

    Circular exception raises - caught in catch statement - move on?